Repository: apache/ozone
Pull request #8251: HDDS-12704. Add missing audit logs for SCM client operations
Author: login: priyeshkaratha
Created: 2025-04-09T06:53:34Z | Merged: 2025-04-17T18:17:43Z

## What changes were proposed in this pull request?
Currently, SCMClientProtocolServer exhibits different behaviors across various operations. In this PR, I have addressed two key issues:

1. **Auditing Enhancements**: Added auditing for operations where it was previously missing.
2. **Admin Access Checks**: Identified and fixed cases where admin access checks were not properly handled due to missing try-catch blocks, which also led to auditing being skipped. These have now been correctly implemented to ensure consistent auditing and access control.

## What is the link to the Apache JIRA

[HDDS-12704](https://issues.apache.org/jira/browse/HDDS-12704)

## How was this patch tested?

There are no functional changes introduced in this PR. I have verified that all existing integration and other test cases pass successfully through [CI actions](https://github.com/priyeshkaratha/ozone/actions/runs/14351311410).



Diff:
diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
index 3b614691bd42..29ff82576eb4 100644
--- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
+++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
@@ -230,43 +230,55 @@ public void join() throws InterruptedException {
   public ContainerWithPipeline allocateContainer(HddsProtos.ReplicationType
       replicationType, HddsProtos.ReplicationFactor factor,
       String owner) throws IOException {
-    if (scm.getScmContext().isInSafeMode()) {
-      throw new SCMException("SafeModePrecheck failed for allocateContainer",
-          ResultCodes.SAFE_MODE_EXCEPTION);
+
+    Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("replicationType", String.valueOf(replicationType));
+    auditMap.put("factor", String.valueOf(factor));
+    auditMap.put("owner", String.valueOf(owner));
+
+    try {
+      if (scm.getScmContext().isInSafeMode()) {
+        throw new SCMException("SafeModePrecheck failed for allocateContainer",
+            ResultCodes.SAFE_MODE_EXCEPTION);
+      }
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      final ContainerInfo container = scm.getContainerManager()
+          .allocateContainer(
+              ReplicationConfig.fromProtoTypeAndFactor(replicationType, factor),
+              owner);
+      final Pipeline pipeline = scm.getPipelineManager()
+          .getPipeline(container.getPipelineID());
+      ContainerWithPipeline cp = new ContainerWithPipeline(container, pipeline);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.ALLOCATE_CONTAINER, auditMap)
+      );
+      return cp;
+    } catch (Exception ex) {
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.ALLOCATE_CONTAINER, auditMap, ex)
+      );
+      throw ex;
     }
-    getScm().checkAdminAccess(getRemoteUser(), false);
-    final ContainerInfo container = scm.getContainerManager()
-        .allocateContainer(
-            ReplicationConfig.fromProtoTypeAndFactor(replicationType, factor),
-            owner);
-    final Pipeline pipeline = scm.getPipelineManager()
-        .getPipeline(container.getPipelineID());
-    return new ContainerWithPipeline(container, pipeline);
   }
 
   @Override
   public ContainerInfo getContainer(long containerID) throws IOException {
-    boolean auditSuccess = true;
     Map<String, String> auditMap = Maps.newHashMap();
     auditMap.put("containerID", String.valueOf(containerID));
-    getScm().checkAdminAccess(getRemoteUser(), true);
     try {
-      return scm.getContainerManager()
+      getScm().checkAdminAccess(getRemoteUser(), true);
+      ContainerInfo info = scm.getContainerManager()
           .getContainer(ContainerID.valueOf(containerID));
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER, auditMap)
+      );
+      return info;
     } catch (IOException ex) {
-      auditSuccess = false;
-      AUDIT.logReadFailure(
-          buildAuditMessageForFailure(SCMAction.GET_CONTAINER, auditMap, ex)
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER, auditMap, ex)
       );
       throw ex;
-    } finally {
-      if (auditSuccess) {
-        AUDIT.logReadSuccess(
-            buildAuditMessageForSuccess(SCMAction.GET_CONTAINER, auditMap)
-        );
-      }
     }
-
   }
 
   private ContainerWithPipeline getContainerWithPipelineCommon(
@@ -306,18 +318,16 @@ private ContainerWithPipeline getContainerWithPipelineCommon(
   @Override
   public ContainerWithPipeline getContainerWithPipeline(long containerID)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("containerID", ContainerID.valueOf(containerID).toString());
     try {
       ContainerWithPipeline cp = getContainerWithPipelineCommon(containerID);
       AUDIT.logReadSuccess(buildAuditMessageForSuccess(
-          SCMAction.GET_CONTAINER_WITH_PIPELINE,
-          Collections.singletonMap("containerID",
-          ContainerID.valueOf(containerID).toString())));
+          SCMAction.GET_CONTAINER_WITH_PIPELINE, auditMap));
       return cp;
     } catch (IOException ex) {
       AUDIT.logReadFailure(buildAuditMessageForFailure(
-          SCMAction.GET_CONTAINER_WITH_PIPELINE,
-          Collections.singletonMap("containerID",
-              ContainerID.valueOf(containerID).toString()), ex));
+          SCMAction.GET_CONTAINER_WITH_PIPELINE, auditMap, ex));
       throw ex;
     }
   }
@@ -326,23 +336,36 @@ public ContainerWithPipeline getContainerWithPipeline(long containerID)
   public List<HddsProtos.SCMContainerReplicaProto> getContainerReplicas(
       long containerId, int clientVersion) throws IOException {
     List<HddsProtos.SCMContainerReplicaProto> results = new ArrayList<>();
+    Map<String, String> auditMap = new HashMap<>();
+    auditMap.put("containerId", String.valueOf(containerId));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
 
-    Set<ContainerReplica> replicas = getScm().getContainerManager()
-        .getContainerReplicas(ContainerID.valueOf(containerId));
-    for (ContainerReplica r : replicas) {
-      results.add(
-          HddsProtos.SCMContainerReplicaProto.newBuilder()
-              .setContainerID(containerId)
-              .setState(r.getState().toString())
-              .setDatanodeDetails(r.getDatanodeDetails().toProto(clientVersion))
-              .setBytesUsed(r.getBytesUsed())
-              .setPlaceOfBirth(r.getOriginDatanodeId().toString())
-              .setKeyCount(r.getKeyCount())
-              .setSequenceID(r.getSequenceId())
-              .setReplicaIndex(r.getReplicaIndex()).build()
-      );
+    try {
+      Set<ContainerReplica> replicas = getScm().getContainerManager()
+          .getContainerReplicas(ContainerID.valueOf(containerId));
+      for (ContainerReplica r : replicas) {
+        results.add(
+            HddsProtos.SCMContainerReplicaProto.newBuilder()
+                .setContainerID(containerId)
+                .setState(r.getState().toString())
+                .setDatanodeDetails(r.getDatanodeDetails().toProto(clientVersion))
+                .setBytesUsed(r.getBytesUsed())
+                .setPlaceOfBirth(r.getOriginDatanodeId().toString())
+                .setKeyCount(r.getKeyCount())
+                .setSequenceID(r.getSequenceId())
+                .setReplicaIndex(r.getReplicaIndex()).build()
+        );
+      }
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_WITH_PIPELINE_BATCH,
+          auditMap));
+      return results;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_REPLICAS,
+          auditMap, ex));
+      throw ex;
     }
-    return results;
   }
 
   @Override
@@ -579,9 +602,14 @@ public void deleteContainer(long containerID) throws IOException {
 
   @Override
   public Map<String, List<ContainerID>> getContainersOnDecomNode(DatanodeDetails dn) throws IOException {
+    Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("datanodeDetails", String.valueOf(dn));
     try {
-      return scm.getScmDecommissionManager().getContainersPendingReplication(dn);
+      Map<String, List<ContainerID>> result =  scm.getScmDecommissionManager().getContainersPendingReplication(dn);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(SCMAction.GET_CONTAINERS_ON_DECOM_NODE, auditMap));
+      return result;
     } catch (NodeNotFoundException e) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(SCMAction.GET_CONTAINERS_ON_DECOM_NODE, auditMap, e));
       throw new IOException("Failed to get containers list. Unable to find required node", e);
     }
   }
@@ -591,30 +619,44 @@ public List<HddsProtos.Node> queryNode(
       HddsProtos.NodeOperationalState opState, HddsProtos.NodeState state,
       HddsProtos.QueryScope queryScope, String poolName, int clientVersion)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("opState", String.valueOf(opState));
+    auditMap.put("state", String.valueOf(state));
+    auditMap.put("queryScope", String.valueOf(queryScope));
+    auditMap.put("poolName", poolName);
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     if (queryScope == HddsProtos.QueryScope.POOL) {
-      throw new IllegalArgumentException("Not Supported yet");
+      IllegalArgumentException ex =  new IllegalArgumentException("Not Supported yet");
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
-
-    List<HddsProtos.Node> result = new ArrayList<>();
-    for (DatanodeDetails node : queryNode(opState, state)) {
-      try {
+    try {
+      List<HddsProtos.Node> result = new ArrayList<>();
+      for (DatanodeDetails node : queryNode(opState, state)) {
         NodeStatus ns = scm.getScmNodeManager().getNodeStatus(node);
         result.add(HddsProtos.Node.newBuilder()
             .setNodeID(node.toProto(clientVersion))
             .addNodeStates(ns.getHealth())
             .addNodeOperationalStates(ns.getOperationalState())
             .build());
-      } catch (NodeNotFoundException e) {
-        throw new IOException(
-            "An unexpected error occurred querying the NodeStatus", e);
       }
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.QUERY_NODE, auditMap));
+      return result;
+    } catch (NodeNotFoundException e) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, e));
+      throw new IOException("An unexpected error occurred querying the NodeStatus", e);
     }
-    return result;
   }
 
   @Override
   public HddsProtos.Node queryNode(UUID uuid)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("uuid", String.valueOf(uuid));
     HddsProtos.Node result = null;
     try {
       DatanodeDetails node = scm.getScmNodeManager().getNode(DatanodeID.of(uuid));
@@ -627,20 +669,33 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to decommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
@@ -648,11 +703,17 @@ public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean fo
   @Override
   public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().recommissionNodes(nodes);
+      List<DatanodeAdminError> result = scm.getScmDecommissionManager().recommissionNodes(nodes);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to recommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
@@ -660,19 +721,26 @@ public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
   @Override
   public List<DatanodeAdminError> startMaintenanceNodes(List<String> nodes,
       int endInHours, boolean force) throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("endInHours", String.valueOf(endInHours));
+    auditMap.put("force", String.valueOf(force));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager()
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager()
           .startMaintenanceNodes(nodes, endInHours, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.START_MAINTENANCE_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to place nodes into maintenance mode", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.START_MAINTENANCE_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public void closeContainer(long containerID) throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
     final UserGroupInformation remoteUser = getRemoteUser();
     final Map<String, String> auditMap = Maps.newHashMap();
     auditMap.put("containerID", String.valueOf(containerID));
@@ -708,7 +776,7 @@ public void closeContainer(long containerID) throws IOException {
   public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
       HddsProtos.ReplicationFactor factor, HddsProtos.NodePool nodePool)
       throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
+
     Map<String, String> auditMap = Maps.newHashMap();
     if (type != null) {
       auditMap.put("replicationType", type.toString());
@@ -724,6 +792,7 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
       auditMap.put("nodePool", String.join(", ", nodeIpAddresses));
     }
     try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
       Pipeline result = scm.getPipelineManager().createPipeline(
           ReplicationConfig.fromProtoTypeAndFactor(type, factor));
       AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
@@ -737,17 +806,34 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
   }
 
   @Override
-  public List<Pipeline> listPipelines() {
-    AUDIT.logReadSuccess(
-        buildAuditMessageForSuccess(SCMAction.LIST_PIPELINE, null));
-    return scm.getPipelineManager().getPipelines();
+  public List<Pipeline> listPipelines() throws IOException {
+    try {
+      List<Pipeline> pipelines = scm.getPipelineManager().getPipelines();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.LIST_PIPELINE, null));
+      return pipelines;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public Pipeline getPipeline(HddsProtos.PipelineID pipelineID)
       throws IOException {
-    return scm.getPipelineManager().getPipeline(
-        PipelineID.getFromProtobuf(pipelineID));
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("pipelineID", pipelineID.getId());
+    try {
+      Pipeline pipeline = scm.getPipelineManager().getPipeline(PipelineID.getFromProtobuf(pipelineID));
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+              SCMAction.GET_PIPELINE, auditMap));
+      return pipeline;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_PIPELINE, auditMap, ex));
+      throw ex;
+    }
   }
 
   @Override
@@ -808,40 +894,34 @@ public void closePipeline(HddsProtos.PipelineID pipelineID)
 
   @Override
   public ScmInfo getScmInfo() {
-    boolean auditSuccess = true;
     try {
       ScmInfo.Builder builder =
           new ScmInfo.Builder()
               .setClusterId(scm.getScmStorageConfig().getClusterID())
               .setScmId(scm.getScmStorageConfig().getScmId())
               .setPeerRoles(scm.getScmHAManager().getRatisServer().getRatisRoles());
-      return builder.build();
+      ScmInfo info = builder.build();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+            SCMAction.GET_SCM_INFO, null));
+      return info;
     } catch (Exception ex) {
-      auditSuccess = false;
-      AUDIT.logReadFailure(
-          buildAuditMessageForFailure(SCMAction.GET_SCM_INFO, null, ex)
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_SCM_INFO, null, ex)
       );
       throw ex;
-    } finally {
-      if (auditSuccess) {
-        AUDIT.logReadSuccess(
-            buildAuditMessageForSuccess(SCMAction.GET_SCM_INFO, null)
-        );
-      }
     }
   }
 
   @Override
   public void transferLeadership(String newLeaderId)
       throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
-    checkIfCertSignRequestAllowed(scm.getRootCARotationManager(),
-        false, config, "transferLeadership");
 
-    boolean auditSuccess = true;
     Map<String, String> auditMap = Maps.newHashMap();
     auditMap.put("newLeaderId", newLeaderId);
     try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      checkIfCertSignRequestAllowed(scm.getRootCARotationManager(),
+          false, config, "transferLeadership");
       SCMRatisServer scmRatisServer = scm.getScmHAManager().getRatisServer();
       RaftGroup group = scmRatisServer.getDivision().getGroup();
       RaftPeerId targetPeerId;
@@ -864,16 +944,12 @@ public void transferLeadership(String newLeaderId)
       RatisHelper.transferRatisLeadership(scm.getConfiguration(), group,
           targetPeerId, tlsConfig);
     } catch (Exception ex) {
-      auditSuccess = false;
       AUDIT.logReadFailure(buildAuditMessageForFailure(
           SCMAction.TRANSFER_LEADERSHIP, auditMap, ex));
       throw ex;
-    } finally {
-      if (auditSuccess) {
-        AUDIT.logReadSuccess(buildAuditMessageForSuccess(
-            SCMAction.TRANSFER_LEADERSHIP, auditMap));
-      }
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+            SCMAction.TRANSFER_LEADERSHIP, auditMap));
   }
 
   @Override
@@ -883,6 +959,7 @@ public List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
     Map<String, String> auditMap = Maps.newHashMap();
     auditMap.put("count", String.valueOf(count));
     auditMap.put("startTxId", String.valueOf(startTxId));
+
     try {
       result = scm.getScmBlockManager().getDeletedBlockLog()
           .getFailedTransactions(count, startTxId).stream()
@@ -902,12 +979,12 @@ public List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
 
   @Override
   public int resetDeletedBlockRetryCount(List<Long> txIDs) throws IOException {
-    Map<String, String> auditMap = Maps.newHashMap();
-    getScm().checkAdminAccess(getRemoteUser(), false);
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("txIDs", txIDs.toString());
     try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
       int count = scm.getScmBlockManager().getDeletedBlockLog().
           resetCount(txIDs);
-      auditMap.put("txIDs", txIDs.toString());
       AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
           SCMAction.RESET_DELETED_BLOCK_RETRY_COUNT, auditMap));
       return count;
@@ -935,7 +1012,16 @@ public boolean inSafeMode() throws IOException {
   @Override
   public Map<String, Pair<Boolean, String>> getSafeModeRuleStatuses()
       throws IOException {
-    return scm.getRuleStatus();
+    try {
+      Map<String, Pair<Boolean, String>> result = scm.getRuleStatus();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_SAFE_MODE_RULE_STATUSES, null));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_SAFE_MODE_RULE_STATUSES, null, ex));
+      throw ex;
+    }
   }
 
   /**
@@ -946,27 +1032,49 @@ public Map<String, Pair<Boolean, String>> getSafeModeRuleStatuses()
    */
   @Override
   public boolean forceExitSafeMode() throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
-    AUDIT.logWriteSuccess(
-        buildAuditMessageForSuccess(SCMAction.FORCE_EXIT_SAFE_MODE, null)
-    );
-    return scm.exitSafeMode();
+    try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      boolean result = scm.exitSafeMode();
+      AUDIT.logWriteSuccess(
+          buildAuditMessageForSuccess(SCMAction.FORCE_EXIT_SAFE_MODE, null)
+      );
+      return result;
+
+    } catch (Exception ex) {
+      AUDIT.logWriteFailure(
+          buildAuditMessageForFailure(SCMAction.FORCE_EXIT_SAFE_MODE, null, ex)
+      );
+      throw ex;
+    }
   }
 
   @Override
   public void startReplicationManager() throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
-    AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
-        SCMAction.START_REPLICATION_MANAGER, null));
-    scm.getReplicationManager().start();
+    try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      scm.getReplicationManager().start();
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.START_REPLICATION_MANAGER, null));
+
+    } catch (Exception ex) {
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.START_REPLICATION_MANAGER, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public void stopReplicationManager() throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
-    AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
-        SCMAction.STOP_REPLICATION_MANAGER, null));
-    scm.getReplicationManager().stop();
+    try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.STOP_REPLICATION_MANAGER, null));
+      scm.getReplicationManager().stop();
+    } catch (Exception ex) {
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.STOP_REPLICATION_MANAGER, null, ex));
+      throw ex;
+    }
   }
 
   @Override
@@ -986,35 +1094,49 @@ public ReplicationManagerReport getReplicationManagerReport() {
   @Override
   public StatusAndMessages finalizeScmUpgrade(String upgradeClientID) throws
       IOException {
-    // check admin authorization
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("upgradeClientID", upgradeClientID);
     try {
+      // check admin authorization
       getScm().checkAdminAccess(getRemoteUser(), false);
-    } catch (IOException e) {
-      LOG.error("Authorization failed for finalize scm upgrade", e);
-      throw e;
+      // TODO HDDS-6762: Return to the client once the FINALIZATION_STARTED
+      //  checkpoint has been crossed and continue finalizing asynchronously.
+      StatusAndMessages result = scm.getFinalizationManager().finalizeUpgrade(upgradeClientID);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.FINALIZE_SCM_UPGRADE, auditMap));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.FINALIZE_SCM_UPGRADE, auditMap, ex));
+      throw ex;
     }
-    // TODO HDDS-6762: Return to the client once the FINALIZATION_STARTED
-    //  checkpoint has been crossed and continue finalizing asynchronously.
-    return scm.getFinalizationManager().finalizeUpgrade(upgradeClientID);
+
   }
 
   @Override
   public StatusAndMessages queryUpgradeFinalizationProgress(
       String upgradeClientID, boolean force, boolean readonly)
       throws IOException {
-    if (!readonly) {
+    Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("upgradeClientID", upgradeClientID);
+    auditMap.put("force", String.valueOf(force));
+    auditMap.put("readonly", String.valueOf(readonly));
+
+    try {
       // check admin authorization
-      try {
+      if (!readonly) {
         getScm().checkAdminAccess(getRemoteUser(), true);
-      } catch (IOException e) {
-        LOG.error("Authorization failed for query scm upgrade finalization " +
-            "progress", e);
-        throw e;
       }
+      StatusAndMessages result = scm.getFinalizationManager()
+          .queryUpgradeFinalizationProgress(upgradeClientID, force, readonly);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.QUERY_UPGRADE_FINALIZATION_PROGRESS, auditMap));
+      return result;
+    } catch (IOException ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_UPGRADE_FINALIZATION_PROGRESS, auditMap, ex));
+      throw ex;
     }
-
-    return scm.getFinalizationManager()
-        .queryUpgradeFinalizationProgress(upgradeClientID, force, readonly);
   }
 
   @Override
@@ -1030,11 +1152,11 @@ public StartContainerBalancerResponseProto startContainerBalancer(
       Optional<Boolean> networkTopologyEnable,
       Optional<String> includeNodes,
       Optional<String> excludeNodes) throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
-    ContainerBalancerConfiguration cbc =
-        scm.getConfiguration().getObject(ContainerBalancerConfiguration.class);
     Map<String, String> auditMap = Maps.newHashMap();
     try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      ContainerBalancerConfiguration cbc =
+          scm.getConfiguration().getObject(ContainerBalancerConfiguration.class);
       if (threshold.isPresent()) {
         double tsd = threshold.get();
         auditMap.put("threshold", String.valueOf(tsd));
@@ -1160,8 +1282,8 @@ public StartContainerBalancerResponseProto startContainerBalancer(
 
   @Override
   public void stopContainerBalancer() throws IOException {
-    getScm().checkAdminAccess(getRemoteUser(), false);
     try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
       scm.getContainerBalancer().stopBalancer();
       AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
           SCMAction.STOP_CONTAINER_BALANCER, null));
@@ -1212,33 +1334,40 @@ public ContainerBalancerStatusInfoResponseProto getContainerBalancerStatusInfo()
   public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
       String address, String uuid, int clientVersion) throws IOException {
 
-    // check admin authorisation
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("address", address);
+    auditMap.put("uuid", uuid);
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     try {
+      // check admin authorisation
       getScm().checkAdminAccess(getRemoteUser(), true);
-    } catch (IOException e) {
-      LOG.error("Authorization failed", e);
-      throw e;
-    }
+      // get datanodes by ip or uuid
+      List<DatanodeDetails> nodes = new ArrayList<>();
+      if (!Strings.isNullOrEmpty(uuid)) {
+        nodes.add(scm.getScmNodeManager().getNode(DatanodeID.fromUuidString(uuid)));
+      } else if (!Strings.isNullOrEmpty(address)) {
+        nodes = scm.getScmNodeManager().getNodesByAddress(address);
+      } else {
+        throw new IOException(
+            "Could not get datanode with the specified parameters."
+        );
+      }
 
-    // get datanodes by ip or uuid
-    List<DatanodeDetails> nodes = new ArrayList<>();
-    if (!Strings.isNullOrEmpty(uuid)) {
-      nodes.add(scm.getScmNodeManager().getNode(DatanodeID.fromUuidString(uuid)));
-    } else if (!Strings.isNullOrEmpty(address)) {
-      nodes = scm.getScmNodeManager().getNodesByAddress(address);
-    } else {
-      throw new IOException(
-          "Could not get datanode with the specified parameters."
-      );
-    }
+      // get datanode usage info
+      List<HddsProtos.DatanodeUsageInfoProto> infoList = new ArrayList<>();
+      for (DatanodeDetails node : nodes) {
+        infoList.add(getUsageInfoFromDatanodeDetails(node, clientVersion));
+      }
 
-    // get datanode usage info
-    List<HddsProtos.DatanodeUsageInfoProto> infoList = new ArrayList<>();
-    for (DatanodeDetails node : nodes) {
-      infoList.add(getUsageInfoFromDatanodeDetails(node, clientVersion));
-    }
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap));
 
-    return infoList;
+      return infoList;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(SCMAction.GET_DATANODE_USAGE_INFO, auditMap, ex));
+      throw ex;
+    }
   }
 
   /**
@@ -1270,62 +1399,116 @@ public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
       boolean mostUsed, int count, int clientVersion)
       throws IOException, IllegalArgumentException {
 
-    // check admin authorisation
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("mostUsed", String.valueOf(mostUsed));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     try {
+      // check admin authorisation
       getScm().checkAdminAccess(getRemoteUser(), true);
-    } catch (IOException e) {
-      LOG.error("Authorization failed", e);
-      throw e;
-    }
+      if (count < 1) {
+        throw new IllegalArgumentException("The specified parameter count must " +
+            "be an integer greater than zero.");
+      }
+      List<DatanodeUsageInfo> datanodeUsageInfoList =
+          scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
 
-    if (count < 1) {
-      throw new IllegalArgumentException("The specified parameter count must " +
-          "be an integer greater than zero.");
-    }
+      // if count is greater than the size of list containing healthy,
+      // in-service nodes, just set count to that size
+      if (count > datanodeUsageInfoList.size()) {
+        count = datanodeUsageInfoList.size();
+      }
 
-    List<DatanodeUsageInfo> datanodeUsageInfoList =
-        scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
+      // return count number of DatanodeUsageInfoProto
+      List<HddsProtos.DatanodeUsageInfoProto> result =  datanodeUsageInfoList.stream()
+          .map(each -> each.toProto(clientVersion))
+          .limit(count)
+          .collect(Collectors.toList());
 
-    // if count is greater than the size of list containing healthy,
-    // in-service nodes, just set count to that size
-    if (count > datanodeUsageInfoList.size()) {
-      count = datanodeUsageInfoList.size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap, ex));
+      throw ex;
     }
-
-    // return count number of DatanodeUsageInfoProto
-    return datanodeUsageInfoList.stream()
-        .map(each -> each.toProto(clientVersion))
-        .limit(count)
-        .collect(Collectors.toList());
   }
 
   @Override
   public Token<?> getContainerToken(ContainerID containerID)
       throws IOException {
-    UserGroupInformation remoteUser = getRemoteUser();
-    getScm().checkAdminAccess(remoteUser, true);
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("containerID", String.valueOf(containerID));
+    try {
+      UserGroupInformation remoteUser = getRemoteUser();
+      getScm().checkAdminAccess(getRemoteUser(), true);
 
-    return scm.getContainerTokenGenerator()
-        .generateToken(remoteUser.getUserName(), containerID);
+      Token<?> token = scm.getContainerTokenGenerator()
+          .generateToken(remoteUser.getUserName(), containerID);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_TOKEN, auditMap));
+      return token;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_TOKEN, auditMap, ex));
+      throw ex;
+    }
   }
 
   @Override
   public long getContainerCount() throws IOException {
-    return scm.getContainerManager().getContainers().size();
+    try {
+      long count = scm.getContainerManager().getContainers().size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_COUNT, null));
+      return count;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_COUNT, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public long getContainerCount(HddsProtos.LifeCycleState state)
       throws IOException {
-    return scm.getContainerManager().getContainers(state).size();
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("state", String.valueOf(state));
+
+    try {
+      long count = scm.getContainerManager().getContainers(state).size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_COUNT, auditMap));
+      return count;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_COUNT, auditMap, ex));
+      throw ex;
+    }
   }
 
   @Override
   public List<ContainerInfo> getListOfContainers(
       long startContainerID, int count, HddsProtos.LifeCycleState state)
       throws IOException {
-    return scm.getContainerManager().getContainers(
-        ContainerID.valueOf(startContainerID), count, state);
+
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("startContainerID", String.valueOf(startContainerID));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("state", String.valueOf(state));
+    try {
+      List<ContainerInfo> results = scm.getContainerManager().getContainers(
+          ContainerID.valueOf(startContainerID), count, state);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.LIST_CONTAINER, auditMap));
+      return results;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_CONTAINER, auditMap, ex));
+      throw ex;
+    }
   }
 
   /**
@@ -1414,6 +1597,8 @@ public void close() throws IOException {
   @Override
   public DecommissionScmResponseProto decommissionScm(
       String scmId) {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("scmId", scmId);
     Builder decommissionScmResponseBuilder =
         DecommissionScmResponseProto.newBuilder();
 
@@ -1421,17 +1606,32 @@ public DecommissionScmResponseProto decommissionScm(
       getScm().checkAdminAccess(getRemoteUser(), false);
       decommissionScmResponseBuilder
           .setSuccess(scm.removePeerFromHARing(scmId));
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_SCM, auditMap));
     } catch (IOException ex) {
       decommissionScmResponseBuilder
           .setSuccess(false)
           .setErrorMsg(ex.getMessage());
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_SCM, auditMap, ex));
     }
     return decommissionScmResponseBuilder.build();
   }
 
   @Override
   public String getMetrics(String query) throws IOException {
-    FetchMetrics fetchMetrics = new FetchMetrics();
-    return fetchMetrics.getMetrics(query);
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("query", query);
+    try {
+      FetchMetrics fetchMetrics = new FetchMetrics();
+      String metrics = fetchMetrics.getMetrics(query);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_METRICS, auditMap));
+      return metrics;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_METRICS, auditMap, ex));
+      throw ex;
+    }
   }
 }
diff --git a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
index 23f56c342c05..a514bda0d4ff 100644
--- a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
+++ b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
@@ -54,7 +54,21 @@ public enum SCMAction implements AuditAction {
   GET_REPLICATION_MANAGER_REPORT,
   RESET_DELETED_BLOCK_RETRY_COUNT,
   TRANSFER_LEADERSHIP,
-  GET_FAILED_DELETED_BLOCKS_TRANSACTION;
+  GET_FAILED_DELETED_BLOCKS_TRANSACTION,
+  GET_CONTAINER_REPLICAS,
+  GET_CONTAINERS_ON_DECOM_NODE,
+  DECOMMISSION_NODES,
+  START_MAINTENANCE_NODES,
+  GET_SAFE_MODE_RULE_STATUSES,
+  FINALIZE_SCM_UPGRADE,
+  QUERY_UPGRADE_FINALIZATION_PROGRESS,
+  GET_DATANODE_USAGE_INFO,
+  GET_CONTAINER_TOKEN,
+  GET_CONTAINER_COUNT,
+  DECOMMISSION_SCM,
+  GET_METRICS,
+  QUERY_NODE,
+  GET_PIPELINE;
 
   @Override
   public String getAction() {


Reviews:
user: login: adoroszlai
body: Thanks @priyeshkaratha for the patch.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T19:18:57Z
user: login: priyeshkaratha
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T12:08:07Z
user: login: priyeshkaratha
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T12:11:42Z
user: login: adoroszlai
body: Thanks @priyeshkaratha for updating the patch.  I'll take a look later, just quick response on the `GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH` request.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T13:04:43Z
user: login: priyeshkaratha
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-10T15:11:02Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T07:19:00Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T07:15:53Z
user: login: adoroszlai
body: Thanks @priyeshkaratha for updating the patch.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T04:31:21Z
user: login: peterxcli
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T04:32:14Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T04:47:28Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T04:48:48Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T04:55:01Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T04:57:06Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T05:03:33Z
user: login: priyeshkaratha
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T05:49:27Z
user: login: priyeshkaratha
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T05:49:43Z
user: login: priyeshkaratha
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T05:51:04Z
user: login: priyeshkaratha
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T05:54:29Z
user: login: peterxcli
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-17T06:14:48Z
user: login: adoroszlai
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T06:18:37Z
user: login: peterxcli
body: Thanks @priyeshkaratha for updating the patch, LGTM!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-17T06:21:40Z

Review comments:
diff_hunk: @@ -215,10 +215,14 @@ public void stop() {
     try {
       LOG.info("Stopping the RPC server for Client Protocol");
       getClientRpcServer().stop();
+
     } catch (Exception ex) {
-      LOG.error("Client Protocol RPC stop failed.", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.STOP_SERVER, null, ex));
     }
     IOUtils.cleanupWithLogger(LOG, scm.getScmNodeManager());
+    AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+        SCMAction.STOP_SERVER, null));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Stopping the server is not a client operation, does not need to be audited.
created_at: 2025-04-09T07:12:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1425,13 +1594,26 @@ public DecommissionScmResponseProto decommissionScm(
       decommissionScmResponseBuilder
           .setSuccess(false)
           .setErrorMsg(ex.getMessage());
+      AUDIT.logWriteSuccess(buildAuditMessageForFailure(
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Both should be failure.
created_at: 2025-04-09T18:05:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1425,13 +1594,26 @@ public DecommissionScmResponseProto decommissionScm(
       decommissionScmResponseBuilder
           .setSuccess(false)
           .setErrorMsg(ex.getMessage());
+      AUDIT.logWriteSuccess(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_SCM, Collections.singletonMap("scmId", scmId), ex));
     }
+    AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+        SCMAction.DECOMMISSION_SCM, Collections.singletonMap("scmId", scmId)));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Please move inside `try`.  Instead of throwing exception, this method returns response for both success and failure.  Thus, two audit log entries would be created for failure case.
created_at: 2025-04-09T18:06:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1414,6 +1582,7 @@ public void close() throws IOException {
   @Override
   public DecommissionScmResponseProto decommissionScm(
       String scmId) {
+
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: let's not add empty lines
created_at: 2025-04-09T18:07:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1270,60 +1409,89 @@ public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
       boolean mostUsed, int count, int clientVersion)
       throws IOException, IllegalArgumentException {
 
-    // check admin authorisation
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("mostUsed", String.valueOf(mostUsed));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     try {
+      // check admin authorisation
       getScm().checkAdminAccess(getRemoteUser(), true);
-    } catch (IOException e) {
-      LOG.error("Authorization failed", e);
-      throw e;
-    }
+      if (count < 1) {
+        throw new IllegalArgumentException("The specified parameter count must " +
+            "be an integer greater than zero.");
+      }
+      List<DatanodeUsageInfo> datanodeUsageInfoList =
+          scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
 
-    if (count < 1) {
-      throw new IllegalArgumentException("The specified parameter count must " +
-          "be an integer greater than zero.");
-    }
+      // if count is greater than the size of list containing healthy,
+      // in-service nodes, just set count to that size
+      if (count > datanodeUsageInfoList.size()) {
+        count = datanodeUsageInfoList.size();
+      }
 
-    List<DatanodeUsageInfo> datanodeUsageInfoList =
-        scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
+      // return count number of DatanodeUsageInfoProto
+      List<HddsProtos.DatanodeUsageInfoProto> result =  datanodeUsageInfoList.stream()
+          .map(each -> each.toProto(clientVersion))
+          .limit(count)
+          .collect(Collectors.toList());
 
-    // if count is greater than the size of list containing healthy,
-    // in-service nodes, just set count to that size
-    if (count > datanodeUsageInfoList.size()) {
-      count = datanodeUsageInfoList.size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap, ex));
+      throw ex;
     }
-
-    // return count number of DatanodeUsageInfoProto
-    return datanodeUsageInfoList.stream()
-        .map(each -> each.toProto(clientVersion))
-        .limit(count)
-        .collect(Collectors.toList());
   }
 
   @Override
   public Token<?> getContainerToken(ContainerID containerID)
       throws IOException {
-    UserGroupInformation remoteUser = getRemoteUser();
-    getScm().checkAdminAccess(remoteUser, true);
+    try {
+      UserGroupInformation remoteUser = getRemoteUser();
+      getScm().checkAdminAccess(getRemoteUser(), true);
 
-    return scm.getContainerTokenGenerator()
-        .generateToken(remoteUser.getUserName(), containerID);
+      Token<?> token =  scm.getContainerTokenGenerator()
+          .generateToken(remoteUser.getUserName(), containerID);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID))));
+      return token;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
+      throw ex;
+    }
   }
 
   @Override
   public long getContainerCount() throws IOException {
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_CONTAINER_COUNT, null));
     return scm.getContainerManager().getContainers().size();
   }
 
   @Override
   public long getContainerCount(HddsProtos.LifeCycleState state)
       throws IOException {
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_CONTAINER_COUNT, Collections.singletonMap("state", String.valueOf(state))));
     return scm.getContainerManager().getContainers(state).size();
   }
 
   @Override
   public List<ContainerInfo> getListOfContainers(
       long startContainerID, int count, HddsProtos.LifeCycleState state)
       throws IOException {
+
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("startContainerID", String.valueOf(startContainerID));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("state", String.valueOf(state));
+
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.LIST_CONTAINER, auditMap));
     return scm.getContainerManager().getContainers(
         ContainerID.valueOf(startContainerID), count, state);
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: 1. This could log success and then throw exception.
2. Failure is not logged.

Please wrap in `try-catch`, and make sure no processing is performed after `logReadSuccess`.
created_at: 2025-04-09T18:12:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1270,60 +1409,89 @@ public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
       boolean mostUsed, int count, int clientVersion)
       throws IOException, IllegalArgumentException {
 
-    // check admin authorisation
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("mostUsed", String.valueOf(mostUsed));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     try {
+      // check admin authorisation
       getScm().checkAdminAccess(getRemoteUser(), true);
-    } catch (IOException e) {
-      LOG.error("Authorization failed", e);
-      throw e;
-    }
+      if (count < 1) {
+        throw new IllegalArgumentException("The specified parameter count must " +
+            "be an integer greater than zero.");
+      }
+      List<DatanodeUsageInfo> datanodeUsageInfoList =
+          scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
 
-    if (count < 1) {
-      throw new IllegalArgumentException("The specified parameter count must " +
-          "be an integer greater than zero.");
-    }
+      // if count is greater than the size of list containing healthy,
+      // in-service nodes, just set count to that size
+      if (count > datanodeUsageInfoList.size()) {
+        count = datanodeUsageInfoList.size();
+      }
 
-    List<DatanodeUsageInfo> datanodeUsageInfoList =
-        scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
+      // return count number of DatanodeUsageInfoProto
+      List<HddsProtos.DatanodeUsageInfoProto> result =  datanodeUsageInfoList.stream()
+          .map(each -> each.toProto(clientVersion))
+          .limit(count)
+          .collect(Collectors.toList());
 
-    // if count is greater than the size of list containing healthy,
-    // in-service nodes, just set count to that size
-    if (count > datanodeUsageInfoList.size()) {
-      count = datanodeUsageInfoList.size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap, ex));
+      throw ex;
     }
-
-    // return count number of DatanodeUsageInfoProto
-    return datanodeUsageInfoList.stream()
-        .map(each -> each.toProto(clientVersion))
-        .limit(count)
-        .collect(Collectors.toList());
   }
 
   @Override
   public Token<?> getContainerToken(ContainerID containerID)
       throws IOException {
-    UserGroupInformation remoteUser = getRemoteUser();
-    getScm().checkAdminAccess(remoteUser, true);
+    try {
+      UserGroupInformation remoteUser = getRemoteUser();
+      getScm().checkAdminAccess(getRemoteUser(), true);
 
-    return scm.getContainerTokenGenerator()
-        .generateToken(remoteUser.getUserName(), containerID);
+      Token<?> token =  scm.getContainerTokenGenerator()
+          .generateToken(remoteUser.getUserName(), containerID);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID))));
+      return token;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
+      throw ex;
+    }
   }
 
   @Override
   public long getContainerCount() throws IOException {
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_CONTAINER_COUNT, null));
     return scm.getContainerManager().getContainers().size();
   }
 
   @Override
   public long getContainerCount(HddsProtos.LifeCycleState state)
       throws IOException {
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_CONTAINER_COUNT, Collections.singletonMap("state", String.valueOf(state))));
     return scm.getContainerManager().getContainers(state).size();
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: 1. This could log success and then throw exception.
2. Failure is not logged.
created_at: 2025-04-09T18:13:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1270,60 +1409,89 @@ public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
       boolean mostUsed, int count, int clientVersion)
       throws IOException, IllegalArgumentException {
 
-    // check admin authorisation
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("mostUsed", String.valueOf(mostUsed));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     try {
+      // check admin authorisation
       getScm().checkAdminAccess(getRemoteUser(), true);
-    } catch (IOException e) {
-      LOG.error("Authorization failed", e);
-      throw e;
-    }
+      if (count < 1) {
+        throw new IllegalArgumentException("The specified parameter count must " +
+            "be an integer greater than zero.");
+      }
+      List<DatanodeUsageInfo> datanodeUsageInfoList =
+          scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
 
-    if (count < 1) {
-      throw new IllegalArgumentException("The specified parameter count must " +
-          "be an integer greater than zero.");
-    }
+      // if count is greater than the size of list containing healthy,
+      // in-service nodes, just set count to that size
+      if (count > datanodeUsageInfoList.size()) {
+        count = datanodeUsageInfoList.size();
+      }
 
-    List<DatanodeUsageInfo> datanodeUsageInfoList =
-        scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
+      // return count number of DatanodeUsageInfoProto
+      List<HddsProtos.DatanodeUsageInfoProto> result =  datanodeUsageInfoList.stream()
+          .map(each -> each.toProto(clientVersion))
+          .limit(count)
+          .collect(Collectors.toList());
 
-    // if count is greater than the size of list containing healthy,
-    // in-service nodes, just set count to that size
-    if (count > datanodeUsageInfoList.size()) {
-      count = datanodeUsageInfoList.size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap, ex));
+      throw ex;
     }
-
-    // return count number of DatanodeUsageInfoProto
-    return datanodeUsageInfoList.stream()
-        .map(each -> each.toProto(clientVersion))
-        .limit(count)
-        .collect(Collectors.toList());
   }
 
   @Override
   public Token<?> getContainerToken(ContainerID containerID)
       throws IOException {
-    UserGroupInformation remoteUser = getRemoteUser();
-    getScm().checkAdminAccess(remoteUser, true);
+    try {
+      UserGroupInformation remoteUser = getRemoteUser();
+      getScm().checkAdminAccess(getRemoteUser(), true);
 
-    return scm.getContainerTokenGenerator()
-        .generateToken(remoteUser.getUserName(), containerID);
+      Token<?> token =  scm.getContainerTokenGenerator()
+          .generateToken(remoteUser.getUserName(), containerID);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID))));
+      return token;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
+      throw ex;
+    }
   }
 
   @Override
   public long getContainerCount() throws IOException {
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_CONTAINER_COUNT, null));
     return scm.getContainerManager().getContainers().size();
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: 1. This could log success and then throw exception.
2. Failure is not logged.
created_at: 2025-04-09T18:13:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1270,60 +1409,89 @@ public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
       boolean mostUsed, int count, int clientVersion)
       throws IOException, IllegalArgumentException {
 
-    // check admin authorisation
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("mostUsed", String.valueOf(mostUsed));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     try {
+      // check admin authorisation
       getScm().checkAdminAccess(getRemoteUser(), true);
-    } catch (IOException e) {
-      LOG.error("Authorization failed", e);
-      throw e;
-    }
+      if (count < 1) {
+        throw new IllegalArgumentException("The specified parameter count must " +
+            "be an integer greater than zero.");
+      }
+      List<DatanodeUsageInfo> datanodeUsageInfoList =
+          scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
 
-    if (count < 1) {
-      throw new IllegalArgumentException("The specified parameter count must " +
-          "be an integer greater than zero.");
-    }
+      // if count is greater than the size of list containing healthy,
+      // in-service nodes, just set count to that size
+      if (count > datanodeUsageInfoList.size()) {
+        count = datanodeUsageInfoList.size();
+      }
 
-    List<DatanodeUsageInfo> datanodeUsageInfoList =
-        scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
+      // return count number of DatanodeUsageInfoProto
+      List<HddsProtos.DatanodeUsageInfoProto> result =  datanodeUsageInfoList.stream()
+          .map(each -> each.toProto(clientVersion))
+          .limit(count)
+          .collect(Collectors.toList());
 
-    // if count is greater than the size of list containing healthy,
-    // in-service nodes, just set count to that size
-    if (count > datanodeUsageInfoList.size()) {
-      count = datanodeUsageInfoList.size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap, ex));
+      throw ex;
     }
-
-    // return count number of DatanodeUsageInfoProto
-    return datanodeUsageInfoList.stream()
-        .map(each -> each.toProto(clientVersion))
-        .limit(count)
-        .collect(Collectors.toList());
   }
 
   @Override
   public Token<?> getContainerToken(ContainerID containerID)
       throws IOException {
-    UserGroupInformation remoteUser = getRemoteUser();
-    getScm().checkAdminAccess(remoteUser, true);
+    try {
+      UserGroupInformation remoteUser = getRemoteUser();
+      getScm().checkAdminAccess(getRemoteUser(), true);
 
-    return scm.getContainerTokenGenerator()
-        .generateToken(remoteUser.getUserName(), containerID);
+      Token<?> token =  scm.getContainerTokenGenerator()
+          .generateToken(remoteUser.getUserName(), containerID);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID))));
+      return token;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_TOKEN, Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Please store audit map in local variable to reduce duplication.
created_at: 2025-04-09T18:14:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -382,10 +411,14 @@ public List<ContainerWithPipeline> getExistContainerWithPipelinesInBatch(
         ContainerWithPipeline cp = getContainerWithPipelineCommon(containerID);
         cpList.add(cp);
       } catch (IOException ex) {
-        //not found , just go ahead
-        LOG.error("Container with common pipeline not found: {}", ex);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+            Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
       }
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+        Collections.singletonMap("containerIDs", containerIDs.toString())));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Please move inside `try`, otherwise two audit entries will be created in case of failure.
created_at: 2025-04-09T18:20:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -579,10 +612,15 @@ public void deleteContainer(long containerID) throws IOException {
 
   @Override
   public Map<String, List<ContainerID>> getContainersOnDecomNode(DatanodeDetails dn) throws IOException {
+    Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("datanodeDetails", String.valueOf(dn));
     try {
-      return scm.getScmDecommissionManager().getContainersPendingReplication(dn);
-    } catch (NodeNotFoundException e) {
-      throw new IOException("Failed to get containers list. Unable to find required node", e);
+      Map<String, List<ContainerID>> result =  scm.getScmDecommissionManager().getContainersPendingReplication(dn);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(SCMAction.GET_CONTAINERS_ON_DECOM_NODE, auditMap));
+      return result;
+    } catch (NodeNotFoundException ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(SCMAction.GET_CONTAINERS_ON_DECOM_NODE, auditMap, ex));
+      throw new IOException("Failed to get containers list. Unable to find required node", ex);
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: let's avoid unnecessary change (i.e. renaming `e -> ex`)
created_at: 2025-04-09T18:39:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -605,10 +653,14 @@ public List<HddsProtos.Node> queryNode(
             .addNodeOperationalStates(ns.getOperationalState())
             .build());
       } catch (NodeNotFoundException e) {
-        throw new IOException(
-            "An unexpected error occurred querying the NodeStatus", e);
+        IOException ex = new  IOException("An unexpected error occurred querying the NodeStatus", e);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.QUERY_NODE, auditMap, ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Pass the original exception (`NodeNotFoundException e`) to audit instead of the constructed one (`IOException ex`).

nit: let's avoid unnecessary change (i.e. renaming `e -> ex`)
created_at: 2025-04-09T18:41:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -627,45 +679,72 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(SCMAction.QUERY_NODE_BY_UUID,
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: `QUERY_NODE` action can be used, instead of introducing another one (`QUERY_NODE_BY_UUID`).  Parameters will indicate the specific method invoked.
created_at: 2025-04-09T18:46:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -986,35 +1106,47 @@ public ReplicationManagerReport getReplicationManagerReport() {
   @Override
   public StatusAndMessages finalizeScmUpgrade(String upgradeClientID) throws
       IOException {
-    // check admin authorization
     try {
+      // check admin authorization
       getScm().checkAdminAccess(getRemoteUser(), false);
-    } catch (IOException e) {
-      LOG.error("Authorization failed for finalize scm upgrade", e);
-      throw e;
+      // TODO HDDS-6762: Return to the client once the FINALIZATION_STARTED
+      //  checkpoint has been crossed and continue finalizing asynchronously.
+      StatusAndMessages result = scm.getFinalizationManager().finalizeUpgrade(upgradeClientID);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.FINALIZE_SCM_UPGRADE, Collections.singletonMap("upgradeClientID", upgradeClientID)));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: please store audit map in variable to avoid duplication.
created_at: 2025-04-09T18:53:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -382,10 +411,14 @@ public List<ContainerWithPipeline> getExistContainerWithPipelinesInBatch(
         ContainerWithPipeline cp = getContainerWithPipelineCommon(containerID);
         cpList.add(cp);
       } catch (IOException ex) {
-        //not found , just go ahead
-        LOG.error("Container with common pipeline not found: {}", ex);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+            Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: Please store map in variable to reduce duplication.
created_at: 2025-04-09T19:18:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -382,10 +411,14 @@ public List<ContainerWithPipeline> getExistContainerWithPipelinesInBatch(
         ContainerWithPipeline cp = getContainerWithPipelineCommon(containerID);
         cpList.add(cp);
       } catch (IOException ex) {
-        //not found , just go ahead
-        LOG.error("Container with common pipeline not found: {}", ex);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+            Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: priyeshkaratha
body: Since auditing is done inside a loop and we're not stopping on exceptions, we need to initialize a separate audit map here, apart from the one used for successful cases. Handled in other place as per your recommendation.
created_at: 2025-04-10T12:08:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -382,10 +411,14 @@ public List<ContainerWithPipeline> getExistContainerWithPipelinesInBatch(
         ContainerWithPipeline cp = getContainerWithPipelineCommon(containerID);
         cpList.add(cp);
       } catch (IOException ex) {
-        //not found , just go ahead
-        LOG.error("Container with common pipeline not found: {}", ex);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+            Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
       }
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+        Collections.singletonMap("containerIDs", containerIDs.toString())));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: priyeshkaratha
body: here on IOException, its continue on loop for next entries and there are chances for success and failures, so should I add list of ids that is success into success audit logs.
created_at: 2025-04-10T12:11:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -377,15 +402,21 @@ public List<ContainerWithPipeline> getContainerWithPipelineBatch(
   public List<ContainerWithPipeline> getExistContainerWithPipelinesInBatch(
       List<Long> containerIDs) {
     List<ContainerWithPipeline> cpList = new ArrayList<>();
+    List<Long> succeededContainers = new ArrayList<>();
     for (Long containerID : containerIDs) {
       try {
         ContainerWithPipeline cp = getContainerWithPipelineCommon(containerID);
         cpList.add(cp);
+        succeededContainers.add(containerID);
       } catch (IOException ex) {
-        //not found , just go ahead
-        LOG.error("Container with common pipeline not found: {}", ex);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+            Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
       }
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+        Collections.singletonMap("containerIDs", succeededContainers.toString())));
     return cpList;
   }
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: I just realized that this is duplicate of `getContainerWithPipelineBatch`, intended as  internal request exposed for Recon.  Let's not add audit for now, we'll check later.
created_at: 2025-04-10T13:02:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -377,15 +402,21 @@ public List<ContainerWithPipeline> getContainerWithPipelineBatch(
   public List<ContainerWithPipeline> getExistContainerWithPipelinesInBatch(
       List<Long> containerIDs) {
     List<ContainerWithPipeline> cpList = new ArrayList<>();
+    List<Long> succeededContainers = new ArrayList<>();
     for (Long containerID : containerIDs) {
       try {
         ContainerWithPipeline cp = getContainerWithPipelineCommon(containerID);
         cpList.add(cp);
+        succeededContainers.add(containerID);
       } catch (IOException ex) {
-        //not found , just go ahead
-        LOG.error("Container with common pipeline not found: {}", ex);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+            Collections.singletonMap("containerID", String.valueOf(containerID)), ex));
       }
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_EXIST_CONTAINER_WITH_PIPELINE_BATCH,
+        Collections.singletonMap("containerIDs", succeededContainers.toString())));
     return cpList;
   }
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: priyeshkaratha
body: Thanks @adoroszlai . I have handled it.
created_at: 2025-04-10T15:11:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1421,17 +1607,30 @@ public DecommissionScmResponseProto decommissionScm(
       getScm().checkAdminAccess(getRemoteUser(), false);
       decommissionScmResponseBuilder
           .setSuccess(scm.removePeerFromHARing(scmId));
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_SCM, Collections.singletonMap("scmId", scmId)));
     } catch (IOException ex) {
       decommissionScmResponseBuilder
           .setSuccess(false)
           .setErrorMsg(ex.getMessage());
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_SCM, Collections.singletonMap("scmId", scmId), ex));
     }
     return decommissionScmResponseBuilder.build();
   }
 
   @Override
   public String getMetrics(String query) throws IOException {
-    FetchMetrics fetchMetrics = new FetchMetrics();
-    return fetchMetrics.getMetrics(query);
+    try {
+      FetchMetrics fetchMetrics = new FetchMetrics();
+      String metrics = fetchMetrics.getMetrics(query);
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_METRICS, Collections.singletonMap("query", query)));
+      return metrics;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_METRICS, Collections.singletonMap("query", query), ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: please store audit map in variable to avoid duplication
created_at: 2025-04-15T06:32:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1421,17 +1607,30 @@ public DecommissionScmResponseProto decommissionScm(
       getScm().checkAdminAccess(getRemoteUser(), false);
       decommissionScmResponseBuilder
           .setSuccess(scm.removePeerFromHARing(scmId));
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_SCM, Collections.singletonMap("scmId", scmId)));
     } catch (IOException ex) {
       decommissionScmResponseBuilder
           .setSuccess(false)
           .setErrorMsg(ex.getMessage());
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_SCM, Collections.singletonMap("scmId", scmId), ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: please store audit map in variable to avoid duplication
created_at: 2025-04-15T06:32:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -54,7 +54,20 @@ public enum SCMAction implements AuditAction {
   GET_REPLICATION_MANAGER_REPORT,
   RESET_DELETED_BLOCK_RETRY_COUNT,
   TRANSFER_LEADERSHIP,
-  GET_FAILED_DELETED_BLOCKS_TRANSACTION;
+  GET_CONTAINER_REPLICAS,
+  GET_FAILED_DELETED_BLOCKS_TRANSACTION,
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
user: login: adoroszlai
body: Note: usually enum values should be added at the end, keeping existing ones unchanged, for compatibility.  In this case I don't think it matters, since values of `SCMAction` are not persisted or sent to remote node.
created_at: 2025-04-15T06:38:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -627,45 +670,72 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(SCMAction.QUERY_NODE,
+          Collections.singletonMap("uuid", String.valueOf(uuid)), ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(SCMAction.QUERY_NODE,
+        Collections.singletonMap("uuid", String.valueOf(uuid))));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: please store audit map in variable to avoid duplication
created_at: 2025-04-15T06:48:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -737,17 +808,32 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
   }
 
   @Override
-  public List<Pipeline> listPipelines() {
-    AUDIT.logReadSuccess(
-        buildAuditMessageForSuccess(SCMAction.LIST_PIPELINE, null));
-    return scm.getPipelineManager().getPipelines();
+  public List<Pipeline> listPipelines() throws IOException {
+    try {
+      List<Pipeline> pipelines = scm.getPipelineManager().getPipelines();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.LIST_PIPELINE, null));
+      return pipelines;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public Pipeline getPipeline(HddsProtos.PipelineID pipelineID)
       throws IOException {
-    return scm.getPipelineManager().getPipeline(
-        PipelineID.getFromProtobuf(pipelineID));
+    try {
+      Pipeline pipeline = scm.getPipelineManager().getPipeline(PipelineID.getFromProtobuf(pipelineID));
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+              SCMAction.LIST_PIPELINE, Collections.singletonMap("pipelineID", String.valueOf(pipelineID))));
+      return pipeline;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, Collections.singletonMap("pipelineID", String.valueOf(pipelineID)), ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: please store audit map in variable to avoid duplication
created_at: 2025-04-15T06:48:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -737,17 +808,32 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
   }
 
   @Override
-  public List<Pipeline> listPipelines() {
-    AUDIT.logReadSuccess(
-        buildAuditMessageForSuccess(SCMAction.LIST_PIPELINE, null));
-    return scm.getPipelineManager().getPipelines();
+  public List<Pipeline> listPipelines() throws IOException {
+    try {
+      List<Pipeline> pipelines = scm.getPipelineManager().getPipelines();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.LIST_PIPELINE, null));
+      return pipelines;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public Pipeline getPipeline(HddsProtos.PipelineID pipelineID)
       throws IOException {
-    return scm.getPipelineManager().getPipeline(
-        PipelineID.getFromProtobuf(pipelineID));
+    try {
+      Pipeline pipeline = scm.getPipelineManager().getPipeline(PipelineID.getFromProtobuf(pipelineID));
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+              SCMAction.LIST_PIPELINE, Collections.singletonMap("pipelineID", String.valueOf(pipelineID))));
+      return pipeline;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, Collections.singletonMap("pipelineID", String.valueOf(pipelineID)), ex));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: This should be `SCMAction.GET_PIPELINE`.
created_at: 2025-04-15T06:52:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -815,33 +901,29 @@ public ScmInfo getScmInfo() {
               .setClusterId(scm.getScmStorageConfig().getClusterID())
               .setScmId(scm.getScmStorageConfig().getScmId())
               .setPeerRoles(scm.getScmHAManager().getRatisServer().getRatisRoles());
-      return builder.build();
+      ScmInfo info =  builder.build();
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: 
```suggestion
      ScmInfo info = builder.build();
```
created_at: 2025-04-15T07:00:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -863,17 +945,14 @@ public void transferLeadership(String newLeaderId)
 
       RatisHelper.transferRatisLeadership(scm.getConfiguration(), group,
           targetPeerId, tlsConfig);
+        
     } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit: let's not add empty lines at the end of blocks
created_at: 2025-04-15T07:03:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -903,8 +983,8 @@ public List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
   @Override
   public int resetDeletedBlockRetryCount(List<Long> txIDs) throws IOException {
     Map<String, String> auditMap = Maps.newHashMap();
-    getScm().checkAdminAccess(getRemoteUser(), false);
     try {
+      getScm().checkAdminAccess(getRemoteUser(), false);
       int count = scm.getScmBlockManager().getDeletedBlockLog().
           resetCount(txIDs);
       auditMap.put("txIDs", txIDs.toString());
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Move `auditMap.put` before `try` block.  Also in `closePipeline`.
created_at: 2025-04-15T07:07:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1270,62 +1402,116 @@ public List<HddsProtos.DatanodeUsageInfoProto> getDatanodeUsageInfo(
       boolean mostUsed, int count, int clientVersion)
       throws IOException, IllegalArgumentException {
 
-    // check admin authorisation
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("mostUsed", String.valueOf(mostUsed));
+    auditMap.put("count", String.valueOf(count));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
+
     try {
+      // check admin authorisation
       getScm().checkAdminAccess(getRemoteUser(), true);
-    } catch (IOException e) {
-      LOG.error("Authorization failed", e);
-      throw e;
-    }
+      if (count < 1) {
+        throw new IllegalArgumentException("The specified parameter count must " +
+            "be an integer greater than zero.");
+      }
+      List<DatanodeUsageInfo> datanodeUsageInfoList =
+          scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
 
-    if (count < 1) {
-      throw new IllegalArgumentException("The specified parameter count must " +
-          "be an integer greater than zero.");
-    }
+      // if count is greater than the size of list containing healthy,
+      // in-service nodes, just set count to that size
+      if (count > datanodeUsageInfoList.size()) {
+        count = datanodeUsageInfoList.size();
+      }
 
-    List<DatanodeUsageInfo> datanodeUsageInfoList =
-        scm.getScmNodeManager().getMostOrLeastUsedDatanodes(mostUsed);
+      // return count number of DatanodeUsageInfoProto
+      List<HddsProtos.DatanodeUsageInfoProto> result =  datanodeUsageInfoList.stream()
+          .map(each -> each.toProto(clientVersion))
+          .limit(count)
+          .collect(Collectors.toList());
 
-    // if count is greater than the size of list containing healthy,
-    // in-service nodes, just set count to that size
-    if (count > datanodeUsageInfoList.size()) {
-      count = datanodeUsageInfoList.size();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap));
+      return result;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_DATANODE_USAGE_INFO, auditMap, ex));
+      throw ex;
     }
-
-    // return count number of DatanodeUsageInfoProto
-    return datanodeUsageInfoList.stream()
-        .map(each -> each.toProto(clientVersion))
-        .limit(count)
-        .collect(Collectors.toList());
   }
 
   @Override
   public Token<?> getContainerToken(ContainerID containerID)
       throws IOException {
-    UserGroupInformation remoteUser = getRemoteUser();
-    getScm().checkAdminAccess(remoteUser, true);
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("containerID", String.valueOf(containerID));
+    try {
+      UserGroupInformation remoteUser = getRemoteUser();
+      getScm().checkAdminAccess(getRemoteUser(), true);
 
-    return scm.getContainerTokenGenerator()
-        .generateToken(remoteUser.getUserName(), containerID);
+      Token<?> token =  scm.getContainerTokenGenerator()
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: nit:

```suggestion
      Token<?> token = scm.getContainerTokenGenerator()
```
created_at: 2025-04-15T07:18:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -737,17 +807,34 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
   }
 
   @Override
-  public List<Pipeline> listPipelines() {
-    AUDIT.logReadSuccess(
-        buildAuditMessageForSuccess(SCMAction.LIST_PIPELINE, null));
-    return scm.getPipelineManager().getPipelines();
+  public List<Pipeline> listPipelines() throws IOException {
+    try {
+      List<Pipeline> pipelines = scm.getPipelineManager().getPipelines();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.LIST_PIPELINE, null));
+      return pipelines;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public Pipeline getPipeline(HddsProtos.PipelineID pipelineID)
       throws IOException {
-    return scm.getPipelineManager().getPipeline(
-        PipelineID.getFromProtobuf(pipelineID));
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("pipelineID", String.valueOf(pipelineID));
+    try {
+      Pipeline pipeline = scm.getPipelineManager().getPipeline(PipelineID.getFromProtobuf(pipelineID));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Sorry, I just noticed that this logs `PipelineID` as proto message, which does not look nice in the log:

```
2025-04-15 11:00:56,041 | INFO  | SCMAudit | user=recon/recon@EXAMPLE.COM | ip=172.20.0.2 | op=GET_PIPELINE {pipelineID=id: "84c958af-43c3-42cd-943f-5ab172cfd6b2"
uuid128 {
  mostSigBits: -8878467680604831027
  leastSigBits: -7764387514381510990
}
} | ret=SUCCESS |  
```

Please use `pipelineID.getId()` for audit map value, like it is for `activatePipeline` and other similar methods.
created_at: 2025-04-16T07:15:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -230,43 +230,55 @@ public void join() throws InterruptedException {
   public ContainerWithPipeline allocateContainer(HddsProtos.ReplicationType
       replicationType, HddsProtos.ReplicationFactor factor,
       String owner) throws IOException {
-    if (scm.getScmContext().isInSafeMode()) {
-      throw new SCMException("SafeModePrecheck failed for allocateContainer",
-          ResultCodes.SAFE_MODE_EXCEPTION);
+
+    Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("replicationType", String.valueOf(replicationType));
+    auditMap.put("factor", String.valueOf(factor));
+    auditMap.put("owner", String.valueOf(owner));
+
+    try {
+      if (scm.getScmContext().isInSafeMode()) {
+        throw new SCMException("SafeModePrecheck failed for allocateContainer",
+            ResultCodes.SAFE_MODE_EXCEPTION);
+      }
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      final ContainerInfo container = scm.getContainerManager()
+          .allocateContainer(
+              ReplicationConfig.fromProtoTypeAndFactor(replicationType, factor),
+              owner);
+      final Pipeline pipeline = scm.getPipelineManager()
+          .getPipeline(container.getPipelineID());
+      ContainerWithPipeline cp = new ContainerWithPipeline(container, pipeline);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.ALLOCATE_CONTAINER, auditMap)
+      );
+      return cp;
+    } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: nit
```suggestion
    } catch (IOException ex) {
```
created_at: 2025-04-17T03:46:44Z
author_association: MEMBER
diff_hunk: @@ -326,22 +336,35 @@ public ContainerWithPipeline getContainerWithPipeline(long containerID)
   public List<HddsProtos.SCMContainerReplicaProto> getContainerReplicas(
       long containerId, int clientVersion) throws IOException {
     List<HddsProtos.SCMContainerReplicaProto> results = new ArrayList<>();
+    Map<String, String> auditMap = new HashMap<>();
+    auditMap.put("containerId", String.valueOf(containerId));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
 
-    Set<ContainerReplica> replicas = getScm().getContainerManager()
-        .getContainerReplicas(ContainerID.valueOf(containerId));
-    for (ContainerReplica r : replicas) {
-      results.add(
-          HddsProtos.SCMContainerReplicaProto.newBuilder()
-              .setContainerID(containerId)
-              .setState(r.getState().toString())
-              .setDatanodeDetails(r.getDatanodeDetails().toProto(clientVersion))
-              .setBytesUsed(r.getBytesUsed())
-              .setPlaceOfBirth(r.getOriginDatanodeId().toString())
-              .setKeyCount(r.getKeyCount())
-              .setSequenceID(r.getSequenceId())
-              .setReplicaIndex(r.getReplicaIndex()).build()
-      );
+    try {
+      Set<ContainerReplica> replicas = getScm().getContainerManager()
+          .getContainerReplicas(ContainerID.valueOf(containerId));
+      for (ContainerReplica r : replicas) {
+        results.add(
+            HddsProtos.SCMContainerReplicaProto.newBuilder()
+                .setContainerID(containerId)
+                .setState(r.getState().toString())
+                .setDatanodeDetails(r.getDatanodeDetails().toProto(clientVersion))
+                .setBytesUsed(r.getBytesUsed())
+                .setPlaceOfBirth(r.getOriginDatanodeId().toString())
+                .setKeyCount(r.getKeyCount())
+                .setSequenceID(r.getSequenceId())
+                .setReplicaIndex(r.getReplicaIndex()).build()
+        );
+      }
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_REPLICAS,
+          auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_CONTAINER_WITH_PIPELINE_BATCH,
+        auditMap));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: Should we also put this into the end of the try block, just like others?
created_at: 2025-04-17T03:50:21Z
author_association: MEMBER
diff_hunk: @@ -605,16 +643,21 @@ public List<HddsProtos.Node> queryNode(
             .addNodeOperationalStates(ns.getOperationalState())
             .build());
       } catch (NodeNotFoundException e) {
-        throw new IOException(
-            "An unexpected error occurred querying the NodeStatus", e);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.QUERY_NODE, auditMap, e));
+        throw new IOException("An unexpected error occurred querying the NodeStatus", e);
       }
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: same question.
created_at: 2025-04-17T03:52:38Z
author_association: MEMBER
diff_hunk: @@ -605,16 +643,21 @@ public List<HddsProtos.Node> queryNode(
             .addNodeOperationalStates(ns.getOperationalState())
             .build());
       } catch (NodeNotFoundException e) {
-        throw new IOException(
-            "An unexpected error occurred querying the NodeStatus", e);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.QUERY_NODE, auditMap, e));
+        throw new IOException("An unexpected error occurred querying the NodeStatus", e);
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: Should this be:
```suggestion
        IOException ex = new IOException("An unexpected error occurred querying the NodeStatus", e);
        AUDIT.logReadFailure(buildAuditMessageForFailure(
            SCMAction.QUERY_NODE, auditMap, ex));
        throw ex
```
or just keep it?
I do see different behaviour on this. https://github.com/apache/ozone/pull/8251/files#diff-02d31f948c607eae697c655f6ec08e36eb5aefec42f57dc53c50751aaadda2e4R672-R680
created_at: 2025-04-17T03:55:34Z
author_association: MEMBER
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: ```suggestion
    } catch (IOException ex) {
```
created_at: 2025-04-17T03:56:49Z
author_association: MEMBER
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to decommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().recommissionNodes(nodes);
+      List<DatanodeAdminError> result = scm.getScmDecommissionManager().recommissionNodes(nodes);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: ditto
created_at: 2025-04-17T03:57:25Z
author_association: MEMBER
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: `scm.getScmDecommissionManager().decommissionNodes` doesnt throw exception.
```suggestion
      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
          SCMAction.DECOMMISSION_NODES, auditMap));
      return List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);;
```
created_at: 2025-04-17T03:59:10Z
author_association: MEMBER
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to decommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().recommissionNodes(nodes);
+      List<DatanodeAdminError> result = scm.getScmDecommissionManager().recommissionNodes(nodes);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to recommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> startMaintenanceNodes(List<String> nodes,
       int endInHours, boolean force) throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("endInHours", String.valueOf(endInHours));
+    auditMap.put("force", String.valueOf(force));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager()
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager()
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: `scm.getScmDecommissionManager().startMaintenanceNodes` doesnt throw, too.
created_at: 2025-04-17T04:00:03Z
author_association: MEMBER
diff_hunk: @@ -737,17 +807,34 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
   }
 
   @Override
-  public List<Pipeline> listPipelines() {
-    AUDIT.logReadSuccess(
-        buildAuditMessageForSuccess(SCMAction.LIST_PIPELINE, null));
-    return scm.getPipelineManager().getPipelines();
+  public List<Pipeline> listPipelines() throws IOException {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: This whole process doesn't throw any error.
created_at: 2025-04-17T04:03:15Z
author_association: MEMBER
diff_hunk: @@ -737,17 +807,34 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
   }
 
   @Override
-  public List<Pipeline> listPipelines() {
-    AUDIT.logReadSuccess(
-        buildAuditMessageForSuccess(SCMAction.LIST_PIPELINE, null));
-    return scm.getPipelineManager().getPipelines();
+  public List<Pipeline> listPipelines() throws IOException {
+    try {
+      List<Pipeline> pipelines = scm.getPipelineManager().getPipelines();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.LIST_PIPELINE, null));
+      return pipelines;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public Pipeline getPipeline(HddsProtos.PipelineID pipelineID)
       throws IOException {
-    return scm.getPipelineManager().getPipeline(
-        PipelineID.getFromProtobuf(pipelineID));
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("pipelineID", pipelineID.getId());
+    try {
+      Pipeline pipeline = scm.getPipelineManager().getPipeline(PipelineID.getFromProtobuf(pipelineID));
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+              SCMAction.GET_PIPELINE, auditMap));
+      return pipeline;
+    } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: ```suggestion
    } catch (PipelineNotFoundException ex) {
```
created_at: 2025-04-17T04:04:57Z
author_association: MEMBER
diff_hunk: @@ -815,33 +902,29 @@ public ScmInfo getScmInfo() {
               .setClusterId(scm.getScmStorageConfig().getClusterID())
               .setScmId(scm.getScmStorageConfig().getScmId())
               .setPeerRoles(scm.getScmHAManager().getRatisServer().getRatisRoles());
-      return builder.build();
+      ScmInfo info = builder.build();
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: please remove the above `boolean auditSuccess = true;` (I cant comment at there)
created_at: 2025-04-17T04:07:12Z
author_association: MEMBER
diff_hunk: @@ -815,33 +902,29 @@ public ScmInfo getScmInfo() {
               .setClusterId(scm.getScmStorageConfig().getClusterID())
               .setScmId(scm.getScmStorageConfig().getScmId())
               .setPeerRoles(scm.getScmHAManager().getRatisServer().getRatisRoles());
-      return builder.build();
+      ScmInfo info = builder.build();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+            SCMAction.GET_SCM_INFO, null));
+      return info;
     } catch (Exception ex) {
-      auditSuccess = false;
-      AUDIT.logReadFailure(
-          buildAuditMessageForFailure(SCMAction.GET_SCM_INFO, null, ex)
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: And I think this doest throw, too.
created_at: 2025-04-17T04:08:01Z
author_association: MEMBER
diff_hunk: @@ -605,16 +643,21 @@ public List<HddsProtos.Node> queryNode(
             .addNodeOperationalStates(ns.getOperationalState())
             .build());
       } catch (NodeNotFoundException e) {
-        throw new IOException(
-            "An unexpected error occurred querying the NodeStatus", e);
+        AUDIT.logReadFailure(buildAuditMessageForFailure(
+            SCMAction.QUERY_NODE, auditMap, e));
+        throw new IOException("An unexpected error occurred querying the NodeStatus", e);
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: No, we want to log the original exception, not the wrapper.
created_at: 2025-04-17T04:47:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -230,43 +230,55 @@ public void join() throws InterruptedException {
   public ContainerWithPipeline allocateContainer(HddsProtos.ReplicationType
       replicationType, HddsProtos.ReplicationFactor factor,
       String owner) throws IOException {
-    if (scm.getScmContext().isInSafeMode()) {
-      throw new SCMException("SafeModePrecheck failed for allocateContainer",
-          ResultCodes.SAFE_MODE_EXCEPTION);
+
+    Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("replicationType", String.valueOf(replicationType));
+    auditMap.put("factor", String.valueOf(factor));
+    auditMap.put("owner", String.valueOf(owner));
+
+    try {
+      if (scm.getScmContext().isInSafeMode()) {
+        throw new SCMException("SafeModePrecheck failed for allocateContainer",
+            ResultCodes.SAFE_MODE_EXCEPTION);
+      }
+      getScm().checkAdminAccess(getRemoteUser(), false);
+      final ContainerInfo container = scm.getContainerManager()
+          .allocateContainer(
+              ReplicationConfig.fromProtoTypeAndFactor(replicationType, factor),
+              owner);
+      final Pipeline pipeline = scm.getPipelineManager()
+          .getPipeline(container.getPipelineID());
+      ContainerWithPipeline cp = new ContainerWithPipeline(container, pipeline);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.ALLOCATE_CONTAINER, auditMap)
+      );
+      return cp;
+    } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Let's keep catching `Exception`, which is better because it handles unchecked exceptions, too.  We may want to change occurrences of `catch (IOException)` to `catch (Exception)` instead.
created_at: 2025-04-17T04:48:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -815,33 +902,29 @@ public ScmInfo getScmInfo() {
               .setClusterId(scm.getScmStorageConfig().getClusterID())
               .setScmId(scm.getScmStorageConfig().getScmId())
               .setPeerRoles(scm.getScmHAManager().getRatisServer().getRatisRoles());
-      return builder.build();
+      ScmInfo info = builder.build();
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Thanks for spotting this.  There are two unused `auditSuccess` declarations:

https://github.com/apache/ozone/blob/d6fcef930ea38ff49e8ac79523afa76b3c1b0829/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java#L898

https://github.com/apache/ozone/blob/d6fcef930ea38ff49e8ac79523afa76b3c1b0829/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java#L921
created_at: 2025-04-17T04:55:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -326,22 +336,35 @@ public ContainerWithPipeline getContainerWithPipeline(long containerID)
   public List<HddsProtos.SCMContainerReplicaProto> getContainerReplicas(
       long containerId, int clientVersion) throws IOException {
     List<HddsProtos.SCMContainerReplicaProto> results = new ArrayList<>();
+    Map<String, String> auditMap = new HashMap<>();
+    auditMap.put("containerId", String.valueOf(containerId));
+    auditMap.put("clientVersion", String.valueOf(clientVersion));
 
-    Set<ContainerReplica> replicas = getScm().getContainerManager()
-        .getContainerReplicas(ContainerID.valueOf(containerId));
-    for (ContainerReplica r : replicas) {
-      results.add(
-          HddsProtos.SCMContainerReplicaProto.newBuilder()
-              .setContainerID(containerId)
-              .setState(r.getState().toString())
-              .setDatanodeDetails(r.getDatanodeDetails().toProto(clientVersion))
-              .setBytesUsed(r.getBytesUsed())
-              .setPlaceOfBirth(r.getOriginDatanodeId().toString())
-              .setKeyCount(r.getKeyCount())
-              .setSequenceID(r.getSequenceId())
-              .setReplicaIndex(r.getReplicaIndex()).build()
-      );
+    try {
+      Set<ContainerReplica> replicas = getScm().getContainerManager()
+          .getContainerReplicas(ContainerID.valueOf(containerId));
+      for (ContainerReplica r : replicas) {
+        results.add(
+            HddsProtos.SCMContainerReplicaProto.newBuilder()
+                .setContainerID(containerId)
+                .setState(r.getState().toString())
+                .setDatanodeDetails(r.getDatanodeDetails().toProto(clientVersion))
+                .setBytesUsed(r.getBytesUsed())
+                .setPlaceOfBirth(r.getOriginDatanodeId().toString())
+                .setKeyCount(r.getKeyCount())
+                .setSequenceID(r.getSequenceId())
+                .setReplicaIndex(r.getReplicaIndex()).build()
+        );
+      }
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.GET_CONTAINER_REPLICAS,
+          auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.GET_CONTAINER_WITH_PIPELINE_BATCH,
+        auditMap));
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: I agree, it's better to move success log and `return` into the `try` block.  This makes it easier to spot problems where exception is not re-thrown (HDDS-12703).
created_at: 2025-04-17T04:57:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to decommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().recommissionNodes(nodes);
+      List<DatanodeAdminError> result = scm.getScmDecommissionManager().recommissionNodes(nodes);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: This excerpt is unlike the one immediately before it.  GitHub may not display your comments in the order you intended.  So comments like "same as above" or "ditto" are hard to understand for the author.

I think it's better to mention in a single comment that there are similar issues, with specific code references if there aren't too many and you have the time.
created_at: 2025-04-17T05:03:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: priyeshkaratha
body: Keeping Exception since it is better because it handles unchecked exceptions
created_at: 2025-04-17T05:49:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -737,17 +807,34 @@ public Pipeline createReplicationPipeline(HddsProtos.ReplicationType type,
   }
 
   @Override
-  public List<Pipeline> listPipelines() {
-    AUDIT.logReadSuccess(
-        buildAuditMessageForSuccess(SCMAction.LIST_PIPELINE, null));
-    return scm.getPipelineManager().getPipelines();
+  public List<Pipeline> listPipelines() throws IOException {
+    try {
+      List<Pipeline> pipelines = scm.getPipelineManager().getPipelines();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+          SCMAction.LIST_PIPELINE, null));
+      return pipelines;
+    } catch (Exception ex) {
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.LIST_PIPELINE, null, ex));
+      throw ex;
+    }
   }
 
   @Override
   public Pipeline getPipeline(HddsProtos.PipelineID pipelineID)
       throws IOException {
-    return scm.getPipelineManager().getPipeline(
-        PipelineID.getFromProtobuf(pipelineID));
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("pipelineID", pipelineID.getId());
+    try {
+      Pipeline pipeline = scm.getPipelineManager().getPipeline(PipelineID.getFromProtobuf(pipelineID));
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+              SCMAction.GET_PIPELINE, auditMap));
+      return pipeline;
+    } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: priyeshkaratha
body: Keeping Exception since it is better because it handles unchecked exceptions
created_at: 2025-04-17T05:49:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to decommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().recommissionNodes(nodes);
+      List<DatanodeAdminError> result = scm.getScmDecommissionManager().recommissionNodes(nodes);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to recommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> startMaintenanceNodes(List<String> nodes,
       int endInHours, boolean force) throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("endInHours", String.valueOf(endInHours));
+    auditMap.put("force", String.valueOf(force));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager()
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager()
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: priyeshkaratha
body: checking admin access may throw exception. 
created_at: 2025-04-17T05:51:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -815,33 +902,29 @@ public ScmInfo getScmInfo() {
               .setClusterId(scm.getScmStorageConfig().getClusterID())
               .setScmId(scm.getScmStorageConfig().getScmId())
               .setPeerRoles(scm.getScmHAManager().getRatisServer().getRatisRoles());
-      return builder.build();
+      ScmInfo info = builder.build();
+      AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+            SCMAction.GET_SCM_INFO, null));
+      return info;
     } catch (Exception ex) {
-      auditSuccess = false;
-      AUDIT.logReadFailure(
-          buildAuditMessageForFailure(SCMAction.GET_SCM_INFO, null, ex)
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: priyeshkaratha
body: Added  for handling unhandled exceptions
created_at: 2025-04-17T05:54:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to decommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().recommissionNodes(nodes);
+      List<DatanodeAdminError> result = scm.getScmDecommissionManager().recommissionNodes(nodes);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: peterxcli
body: Thanks @adoroszlai, will keep in mind.
What I refer here is I think we can return the result retrieved from `scm.getScmDecommissionManager().recommissionNodes(nodes)` directly, as it doesnt throw exception.
```java
  try {
    ...
    AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
        SCMAction.DECOMMISSION_NODES, auditMap));
    return scm.getScmDecommissionManager().recommissionNodes(nodes);
  } catch ...
```
created_at: 2025-04-17T06:14:48Z
author_association: MEMBER
diff_hunk: @@ -627,52 +670,78 @@ public HddsProtos.Node queryNode(UUID uuid)
             .build();
       }
     } catch (NodeNotFoundException e) {
-      throw new IOException(
+      IOException ex = new IOException(
           "An unexpected error occurred querying the NodeStatus", e);
+      AUDIT.logReadFailure(buildAuditMessageForFailure(
+          SCMAction.QUERY_NODE, auditMap, ex));
+      throw ex;
     }
+    AUDIT.logReadSuccess(buildAuditMessageForSuccess(
+        SCMAction.QUERY_NODE, auditMap));
     return result;
   }
 
   @Override
   public List<DatanodeAdminError> decommissionNodes(List<String> nodes, boolean force)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
+    auditMap.put("force", String.valueOf(force));
+
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      List<DatanodeAdminError> result =  scm.getScmDecommissionManager().decommissionNodes(nodes, force);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
-      LOG.error("Failed to decommission nodes", ex);
+      AUDIT.logWriteFailure(buildAuditMessageForFailure(
+          SCMAction.DECOMMISSION_NODES, auditMap, ex));
       throw ex;
     }
   }
 
   @Override
   public List<DatanodeAdminError> recommissionNodes(List<String> nodes)
       throws IOException {
+    final Map<String, String> auditMap = Maps.newHashMap();
+    auditMap.put("nodes", String.valueOf(nodes));
     try {
       getScm().checkAdminAccess(getRemoteUser(), false);
-      return scm.getScmDecommissionManager().recommissionNodes(nodes);
+      List<DatanodeAdminError> result = scm.getScmDecommissionManager().recommissionNodes(nodes);
+      AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+          SCMAction.DECOMMISSION_NODES, auditMap));
+      return result;
     } catch (Exception ex) {
path: hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
user: login: adoroszlai
body: Thanks @peterxcli for the clarification.  Any call may throw unchecked exceptions, so it's better to only have `return` statement after logging success.
created_at: 2025-04-17T06:18:37Z
author_association: CONTRIBUTOR

PR comments:
user: login: adoroszlai
created_at: 2025-04-15T06:18:31Z
body: Please remove duplicate `checkAdminAccess` (the one outside try block):

https://github.com/apache/ozone/blob/929d7178762ffcf92ffd77ac42be78f800aeb3be/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java#L744-L751
author_association: CONTRIBUTOR
user: login: priyeshkaratha
created_at: 2025-04-15T10:01:56Z
body: Thank you @adoroszlai for the detailed review. Addressed all the mentioned changes.
author_association: CONTRIBUTOR
user: login: priyeshkaratha
created_at: 2025-04-17T03:17:01Z
body: @adoroszlai Updated PR with suggested changes. Thanks
author_association: CONTRIBUTOR
user: login: priyeshkaratha
created_at: 2025-04-17T05:55:31Z
body: @peterxcli Thanks for your reviews updated PR with the suggested changes which are applicable
author_association: CONTRIBUTOR
user: login: adoroszlai
created_at: 2025-04-17T18:18:00Z
body: Thanks @priyeshkaratha for the patch, @peterxcli for the review.
author_association: CONTRIBUTOR