This is an automated email from the ASF dual-hosted git repository.

pradeepagrawal8184 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new 63e5bd704 RANGER-5804: Support Ranger Admin for displaying audit 
metrics from OpenSearch (#1251)
63e5bd704 is described below

commit 63e5bd7040954455f89c5f6f4615a92d18093510
Author: Rakesh Gupta <[email protected]>
AuthorDate: Wed Sep 30 13:00:12 2026 +0530

    RANGER-5804: Support Ranger Admin for displaying audit metrics from 
OpenSearch (#1251)
    
    * RANGER-5804: Support Ranger Admin for displaying audit metrics from 
OpenSearch
    
    * RANGER-5804: Support Ranger Admin for displaying audit metrics from 
OpenSearch - fix review comment
---
 .../audit/metrics/AccessAuditsMetricsService.java  |  39 ++
 .../metrics/AccessAuditsMetricsServiceFactory.java |  48 ++
 .../ranger/audit/metrics/AuditMetricsHelper.java   | 248 ++++++++++
 .../opensearch/OpenSearchAccessAuditsService.java  |  52 ++-
 .../opensearch/OpenSearchAuditMetricsHelper.java   | 518 +++++++++++++++++++++
 .../org/apache/ranger/rest/AuditMetricsREST.java   |  25 +-
 .../ranger/solr/SolrAccessAuditsService.java       |   3 +-
 .../apache/ranger/solr/SolrAuditMetricsHelper.java | 185 +-------
 .../AccessAuditsMetricsServiceFactoryTest.java     |  69 +++
 .../OpenSearchAuditMetricsHelperTest.java          | 238 ++++++++++
 .../apache/ranger/rest/TestAuditMetricsREST.java   |  60 +--
 .../ranger/solr/SolrAccessAuditsServiceTest.java   |   4 +-
 .../ranger/solr/SolrAuditMetricsHelperTest.java    |  15 +-
 13 files changed, 1305 insertions(+), 199 deletions(-)

diff --git 
a/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsService.java
 
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsService.java
new file mode 100644
index 000000000..63a07d428
--- /dev/null
+++ 
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsService.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.audit.metrics;
+
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+
+import java.util.List;
+
+public interface AccessAuditsMetricsService {
+    RangerAuditMetrics getLatestAuditMetrics(String serviceType, String 
serviceName, String timezone);
+
+    RangerAuditMetrics getAuditMetrics(Long serviceId, String timezone);
+
+    List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter filter, 
String timezone);
+
+    List<RangerAuditMetricsByDays> getAuditMetricsByDays(int olderThanInDays, 
SearchFilter filter, String timezone);
+
+    List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter 
filter, String timezone);
+}
diff --git 
a/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactory.java
 
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactory.java
new file mode 100644
index 000000000..d1f1f1c07
--- /dev/null
+++ 
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactory.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.audit.metrics;
+
+import org.apache.ranger.biz.RangerBizUtil;
+import org.apache.ranger.opensearch.OpenSearchAccessAuditsService;
+import org.apache.ranger.solr.SolrAccessAuditsService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AccessAuditsMetricsServiceFactory {
+    @Autowired
+    RangerBizUtil rangerBizUtil;
+
+    @Autowired
+    SolrAccessAuditsService solrAccessAuditsService;
+
+    @Autowired
+    OpenSearchAccessAuditsService openSearchAccessAuditsService;
+
+    public AccessAuditsMetricsService getAccessAuditsMetricsService() {
+        AccessAuditsMetricsService ret = solrAccessAuditsService;
+
+        if 
(RangerBizUtil.AUDIT_STORE_OPENSEARCH.equalsIgnoreCase(rangerBizUtil.getAuditDBType()))
 {
+            ret = openSearchAccessAuditsService;
+        }
+
+        return ret;
+    }
+}
diff --git 
a/security-admin/src/main/java/org/apache/ranger/audit/metrics/AuditMetricsHelper.java
 
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AuditMetricsHelper.java
new file mode 100644
index 000000000..ba1a515b1
--- /dev/null
+++ 
b/security-admin/src/main/java/org/apache/ranger/audit/metrics/AuditMetricsHelper.java
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.audit.metrics;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeParseException;
+import java.util.Date;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Component
+public class AuditMetricsHelper {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(AuditMetricsHelper.class);
+
+    public static final long MISSING_REPO_TYPE_SENTINEL = -1L;
+
+    private final Map<String, Long> repoTypeByServiceType = new 
ConcurrentHashMap<>();
+
+    @Autowired
+    RangerDaoManager daoManager;
+
+    public SearchFilter buildSearchFilter(String serviceType, String 
serviceName, String appId, String clusterName, String clientIP) {
+        SearchFilter filter = new SearchFilter();
+
+        filter.setParam(SearchFilter.SERVICE_TYPE, serviceType);
+        filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
+        filter.setParam(SearchFilter.PLUGIN_APP_ID, appId);
+        filter.setParam(SearchFilter.CLUSTER_NAME, clusterName);
+        filter.setParam(SearchFilter.CLIENT_IP, clientIP);
+
+        return filter;
+    }
+
+    public FilterParams getFilterParams(SearchFilter filter) {
+        FilterParams params = new FilterParams();
+
+        if (filter != null) {
+            params.serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
+            params.serviceName = filter.getParam(SearchFilter.SERVICE_NAME);
+            params.appId = filter.getParam(SearchFilter.PLUGIN_APP_ID);
+            params.clusterName = filter.getParam(SearchFilter.CLUSTER_NAME);
+            params.clientIP = filter.getParam(SearchFilter.CLIENT_IP);
+        }
+
+        return params;
+    }
+
+    public RangerAuditMetrics buildAuditMetrics(String serviceType, String 
serviceName, String appId, String clusterName, String clientIP, long count) {
+        RangerAuditMetrics metric = new RangerAuditMetrics();
+
+        metric.setServiceName(serviceName);
+        metric.setServiceType(resolveServiceType(serviceType, serviceName));
+        metric.setAppId(appId);
+        metric.setClusterName(clusterName);
+        metric.setClientIP(clientIP);
+        metric.setNumberOfAudits(count);
+
+        Long serviceId = resolveServiceId(serviceName);
+
+        if (serviceId != null) {
+            metric.setId(serviceId);
+        }
+
+        return metric;
+    }
+
+    public RangerAuditMetricsByDays buildAuditMetricsByDays(FilterParams 
params, Long auditDate, long count) {
+        return new RangerAuditMetricsByDays(params.serviceType, 
params.serviceName, params.appId, params.clusterName, params.clientIP, 
auditDate, count);
+    }
+
+    public RangerAuditMetricsByHours buildAuditMetricsByHours(FilterParams 
params, int hour, long count) {
+        return new RangerAuditMetricsByHours(params.serviceType, 
params.serviceName, params.appId, params.clusterName, params.clientIP, hour, 
count);
+    }
+
+    public Long resolveServiceId(String serviceName) {
+        Long ret = null;
+
+        if (StringUtils.isNotBlank(serviceName) && daoManager != null && 
daoManager.getXXService() != null) {
+            XXService service = 
daoManager.getXXService().findByName(serviceName);
+
+            if (service != null) {
+                ret = service.getId();
+            }
+        }
+
+        return ret;
+    }
+
+    public String resolveServiceType(XXService service) {
+        String ret = null;
+
+        if (service != null && daoManager != null && 
daoManager.getXXServiceDef() != null) {
+            XXServiceDef serviceDef = 
daoManager.getXXServiceDef().getById(service.getType());
+
+            if (serviceDef != null) {
+                ret = serviceDef.getName();
+            }
+        }
+
+        return ret;
+    }
+
+    public String resolveServiceType(String serviceType, String serviceName) {
+        String ret = serviceType;
+
+        if (StringUtils.isBlank(ret)) {
+            if (StringUtils.isNotBlank(serviceName) && daoManager != null && 
daoManager.getXXService() != null) {
+                XXService service = 
daoManager.getXXService().findByName(serviceName);
+                ret = resolveServiceType(service);
+            } else {
+                ret = null;
+            }
+        }
+
+        return ret;
+    }
+
+    public long resolveRepoType(String serviceType) {
+        long ret = MISSING_REPO_TYPE_SENTINEL;
+
+        if (StringUtils.isBlank(serviceType)) {
+            return ret;
+        }
+
+        String cacheKey = serviceType.trim().toLowerCase();
+        Long cached = repoTypeByServiceType.get(cacheKey);
+
+        if (cached != null) {
+            ret = cached;
+            return ret;
+        }
+
+        if (daoManager != null && daoManager.getXXServiceDef() != null) {
+            XXServiceDef serviceDef = 
daoManager.getXXServiceDef().findByName(serviceType);
+
+            if (serviceDef != null && serviceDef.getId() != null) {
+                ret = serviceDef.getId();
+            }
+        }
+
+        repoTypeByServiceType.put(cacheKey, ret);
+
+        return ret;
+    }
+
+    public ZoneId parseZoneId(String timezone) {
+        ZoneId ret = null;
+
+        if (StringUtils.isNotBlank(timezone)) {
+            try {
+                ret = ZoneId.of(timezone.trim());
+            } catch (DateTimeException e) {
+                LOGGER.warn("Invalid timezone value: {}", timezone, e);
+            }
+        }
+
+        return ret;
+    }
+
+    public ZoneId resolveZoneId(String timezone) {
+        ZoneId ret = parseZoneId(timezone);
+
+        if (ret == null) {
+            ret = ZoneOffset.UTC;
+        }
+
+        return ret;
+    }
+
+    public Long parseAuditDate(Object value) {
+        Long ret = null;
+
+        if (value instanceof Date) {
+            ret = ((Date) value).getTime();
+        } else if (value instanceof Number) {
+            ret = ((Number) value).longValue();
+        } else if (value instanceof String) {
+            try {
+                ret = Instant.parse((String) value).toEpochMilli();
+            } catch (DateTimeParseException e) {
+                LOGGER.warn("Unable to parse audit metric date value: {}", 
value, e);
+            }
+        }
+
+        return ret;
+    }
+
+    public static class FilterParams {
+        private String serviceType;
+        private String serviceName;
+        private String appId;
+        private String clusterName;
+        private String clientIP;
+
+        public String getServiceType() {
+            return serviceType;
+        }
+
+        public String getServiceName() {
+            return serviceName;
+        }
+
+        public String getAppId() {
+            return appId;
+        }
+
+        public String getClusterName() {
+            return clusterName;
+        }
+
+        public String getClientIP() {
+            return clientIP;
+        }
+    }
+}
diff --git 
a/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
 
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
index 340ac34df..aa2f979f3 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAccessAuditsService.java
@@ -19,6 +19,8 @@
 
 package org.apache.ranger.opensearch;
 
+import org.apache.ranger.AccessAuditsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
 import org.apache.ranger.audit.provider.MiscUtil;
 import org.apache.ranger.common.MessageEnums;
 import org.apache.ranger.common.PropertiesUtil;
@@ -28,7 +30,11 @@
 import org.apache.ranger.entity.XXService;
 import org.apache.ranger.entity.XXServiceDef;
 import org.apache.ranger.opensearch.OpenSearchUtil.OpenSearchSearchResult;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
 import org.apache.ranger.plugin.util.JsonUtilsV2;
+import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.view.VXAccessAudit;
 import org.apache.ranger.view.VXAccessAuditList;
 import org.apache.ranger.view.VXLong;
@@ -47,7 +53,7 @@
 
 @Service
 @Scope("singleton")
-public class OpenSearchAccessAuditsService extends 
org.apache.ranger.AccessAuditsService {
+public class OpenSearchAccessAuditsService extends AccessAuditsService 
implements AccessAuditsMetricsService {
     private static final Logger LOG = 
LoggerFactory.getLogger(OpenSearchAccessAuditsService.class);
 
     @Autowired
@@ -56,6 +62,9 @@ public class OpenSearchAccessAuditsService extends 
org.apache.ranger.AccessAudit
     @Autowired
     OpenSearchUtil openSearchUtil;
 
+    @Autowired
+    OpenSearchAuditMetricsHelper auditMetricsHelper;
+
     public VXAccessAuditList searchXAccessAudits(SearchCriteria 
searchCriteria) {
         RestClient    client              = openSearchMgr.getClient();
         final boolean hiveQueryVisibility = 
PropertiesUtil.getBooleanProperty("ranger.audit.hive.query.visibility", true);
@@ -132,6 +141,47 @@ public VXLong getXAccessAuditSearchCount(SearchCriteria 
searchCriteria) {
         return vXLong;
     }
 
+    public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String 
serviceName, String timezone) {
+        return auditMetricsHelper.getLatestAuditMetrics(serviceType, 
serviceName, timezone);
+    }
+
+    public RangerAuditMetrics getAuditMetrics(Long serviceId, String timezone) 
{
+        if (serviceId == null) {
+            throw restErrorUtil.createRESTException("AuditMetrics id is 
required");
+        }
+
+        if (daoManager == null || daoManager.getXXService() == null) {
+            throw restErrorUtil.createRESTException("Service lookup is not 
available");
+        }
+
+        XXService service = daoManager.getXXService().getById(serviceId);
+
+        if (service == null) {
+            throw restErrorUtil.createRESTException("AuditMetrics with Id: " + 
serviceId + " does not exist");
+        }
+
+        String serviceName = service.getName();
+        String serviceType = auditMetricsHelper.resolveServiceType(service);
+
+        RangerAuditMetrics metric = 
auditMetricsHelper.getLatestAuditMetrics(serviceType, serviceName, timezone);
+
+        metric.setId(serviceId);
+
+        return metric;
+    }
+
+    public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter 
filter, String timezone) {
+        return auditMetricsHelper.getLatestAuditMetricsList(filter, timezone);
+    }
+
+    public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int 
olderThanInDays, SearchFilter filter, String timezone) {
+        return auditMetricsHelper.getAuditMetricsByDays(olderThanInDays, 
filter, timezone);
+    }
+
+    public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter 
filter, String timezone) {
+        return auditMetricsHelper.getAuditMetricsByHours(filter, timezone);
+    }
+
     private VXAccessAudit populateViewBean(Map<String, Object> source) {
         VXAccessAudit accessAudit = new VXAccessAudit();
         Object        value;
diff --git 
a/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelper.java
 
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelper.java
new file mode 100644
index 000000000..2ff9c62ab
--- /dev/null
+++ 
b/security-admin/src/main/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelper.java
@@ -0,0 +1,518 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.opensearch;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.entity.ContentType;
+import org.apache.http.nio.entity.NStringEntity;
+import org.apache.http.util.EntityUtils;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper.FilterParams;
+import org.apache.ranger.common.MessageEnums;
+import org.apache.ranger.common.RESTErrorUtil;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class OpenSearchAuditMetricsHelper {
+    private static final Logger     LOGGER = 
LoggerFactory.getLogger(OpenSearchAuditMetricsHelper.class);
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    private static final String FACET_REPO     = "per_repo";
+    private static final String FACET_AGENT    = "per_agent";
+    private static final String FACET_CLIIP    = "per_cliip";
+    private static final String FACET_CLUSTER  = "per_cluster";
+    private static final int    AGG_SIZE       = 10000;
+    private static final String MISSING_BUCKET = "";
+
+    @Autowired
+    OpenSearchMgr openSearchMgr;
+
+    @Autowired
+    RESTErrorUtil restErrorUtil;
+
+    @Autowired
+    AuditMetricsHelper auditMetricsHelper;
+
+    public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String 
serviceName, String timezone) {
+        SearchFilter              filter  = 
auditMetricsHelper.buildSearchFilter(serviceType, serviceName, null, null, 
null);
+        List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+        applyLatestRangeFilter(filters, timezone);
+
+        Map<String, Object> queryBody = buildMetricsQueryBody(filters, null);
+        JsonNode            response  = runMetricsSearch(queryBody, "latest 
audit metrics");
+        long                count     = 
response.at("/hits/total/value").asLong(0L);
+
+        return auditMetricsHelper.buildAuditMetrics(serviceType, serviceName, 
null, null, null, count);
+    }
+
+    public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter 
filter, String timezone) {
+        List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+        applyLatestRangeFilter(filters, timezone);
+
+        Map<String, Object> aggregations = buildAuditMetricsListAggregation();
+        Map<String, Object> queryBody    = buildMetricsQueryBody(filters, 
aggregations);
+        JsonNode            response     = runMetricsSearch(queryBody, "audit 
metrics list");
+
+        return extractAuditMetricsList(response, filter);
+    }
+
+    public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int 
olderThanInDays, SearchFilter filter, String timezone) {
+        List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+        applyDaysRangeFilter(filters, olderThanInDays, timezone);
+
+        Map<String, Object> aggregations = buildDayAggregation(timezone);
+        Map<String, Object> queryBody    = buildMetricsQueryBody(filters, 
aggregations);
+        JsonNode            response     = runMetricsSearch(queryBody, "audit 
metrics by days");
+
+        return extractAuditMetricsByDays(response, filter, timezone);
+    }
+
+    public String resolveServiceType(XXService service) {
+        return auditMetricsHelper.resolveServiceType(service);
+    }
+
+    public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter 
filter, String timezone) {
+        List<Map<String, Object>> filters = buildMetricsFilters(filter);
+
+        applyTodayRangeFilter(filters, timezone);
+
+        Map<String, Object> aggregations = buildHourAggregation(timezone);
+        Map<String, Object> queryBody    = buildMetricsQueryBody(filters, 
aggregations);
+        JsonNode            response     = runMetricsSearch(queryBody, "audit 
metrics by hours");
+
+        return extractAuditMetricsByHours(response, filter, timezone);
+    }
+
+    private Map<String, Object> buildMetricsQueryBody(List<Map<String, 
Object>> filters, Map<String, Object> aggregations) {
+        Map<String, Object> queryBody = new LinkedHashMap<>();
+
+        queryBody.put("size", 0);
+
+        Map<String, Object> boolQuery = new LinkedHashMap<>();
+
+        boolQuery.put("filter", filters.isEmpty() ? 
List.of(Map.of("match_all", Map.of())) : filters);
+        queryBody.put("query", Map.of("bool", boolQuery));
+
+        if (aggregations != null) {
+            queryBody.put("aggs", aggregations);
+        }
+
+        return queryBody;
+    }
+
+    private List<Map<String, Object>> buildMetricsFilters(SearchFilter filter) 
{
+        List<Map<String, Object>> filters = new ArrayList<>();
+
+        if (filter == null) {
+            return filters;
+        }
+
+        addMatchFilter(filters, "repo", 
filter.getParam(SearchFilter.SERVICE_NAME));
+        addMatchFilter(filters, "cluster", 
filter.getParam(SearchFilter.CLUSTER_NAME));
+        addMatchFilter(filters, "cliIP", 
filter.getParam(SearchFilter.CLIENT_IP));
+        addMatchFilter(filters, "agent", 
filter.getParam(SearchFilter.PLUGIN_APP_ID));
+
+        String serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
+
+        if (StringUtils.isNotBlank(serviceType)) {
+            long repoType = auditMetricsHelper.resolveRepoType(serviceType);
+
+            if (repoType == AuditMetricsHelper.MISSING_REPO_TYPE_SENTINEL) {
+                filters.add(Map.of("term", Map.of("repoType", -1)));
+            } else {
+                filters.add(Map.of("term", Map.of("repoType", repoType)));
+            }
+        }
+
+        return filters;
+    }
+
+    private void addMatchFilter(List<Map<String, Object>> filters, String 
field, String value) {
+        if (filters == null || StringUtils.isBlank(value)) {
+            return;
+        }
+
+        filters.add(Map.of("match_phrase", Map.of(field, 
value.trim().toLowerCase())));
+    }
+
+    private void applyLatestRangeFilter(List<Map<String, Object>> filters, 
String timezone) {
+        applyRangeFilter(filters, "now-1d", "now", timezone);
+    }
+
+    private void applyTodayRangeFilter(List<Map<String, Object>> filters, 
String timezone) {
+        applyRangeFilter(filters, "now/d", "now", timezone);
+    }
+
+    private void applyDaysRangeFilter(List<Map<String, Object>> filters, int 
olderThanInDays, String timezone) {
+        int daysBack = olderThanInDays - 1;
+
+        applyRangeFilter(filters, "now-" + daysBack + "d/d", "now", timezone);
+    }
+
+    private void applyRangeFilter(List<Map<String, Object>> filters, String 
from, String to, String timezone) {
+        if (filters == null) {
+            return;
+        }
+
+        Map<String, Object> rangeParams = new LinkedHashMap<>();
+
+        rangeParams.put("from", from);
+        rangeParams.put("to", to);
+
+        ZoneId zoneId = auditMetricsHelper.parseZoneId(timezone);
+
+        if (zoneId != null) {
+            rangeParams.put("time_zone", zoneId.getId());
+        }
+
+        filters.add(Map.of("range", Map.of("evtTime", rangeParams)));
+    }
+
+    private Map<String, Object> buildAuditMetricsListAggregation() {
+        Map<String, Object> perClusterTerms = new LinkedHashMap<>();
+
+        perClusterTerms.put("field", "cluster");
+        perClusterTerms.put("size", AGG_SIZE);
+        perClusterTerms.put("missing", MISSING_BUCKET);
+
+        Map<String, Object> perCluster = new LinkedHashMap<>();
+
+        perCluster.put("terms", perClusterTerms);
+
+        Map<String, Object> perCliIpAggs = new LinkedHashMap<>();
+
+        perCliIpAggs.put(FACET_CLUSTER, perCluster);
+
+        Map<String, Object> perCliIpTerms = new LinkedHashMap<>();
+
+        perCliIpTerms.put("field", "cliIP");
+        perCliIpTerms.put("size", AGG_SIZE);
+        perCliIpTerms.put("missing", MISSING_BUCKET);
+
+        Map<String, Object> perCliIp = new LinkedHashMap<>();
+
+        perCliIp.put("terms", perCliIpTerms);
+        perCliIp.put("aggs", perCliIpAggs);
+
+        Map<String, Object> perAgentAggs = new LinkedHashMap<>();
+
+        perAgentAggs.put(FACET_CLIIP, perCliIp);
+
+        Map<String, Object> perAgentTerms = new LinkedHashMap<>();
+
+        perAgentTerms.put("field", "agent");
+        perAgentTerms.put("size", AGG_SIZE);
+        perAgentTerms.put("missing", MISSING_BUCKET);
+
+        Map<String, Object> perAgent = new LinkedHashMap<>();
+
+        perAgent.put("terms", perAgentTerms);
+        perAgent.put("aggs", perAgentAggs);
+
+        Map<String, Object> perRepoAggs = new LinkedHashMap<>();
+
+        perRepoAggs.put(FACET_AGENT, perAgent);
+
+        Map<String, Object> perRepoTerms = new LinkedHashMap<>();
+
+        perRepoTerms.put("field", "repo");
+        perRepoTerms.put("size", AGG_SIZE);
+        perRepoTerms.put("order", Map.of("_count", "desc"));
+
+        Map<String, Object> perRepo = new LinkedHashMap<>();
+
+        perRepo.put("terms", perRepoTerms);
+        perRepo.put("aggs", perRepoAggs);
+
+        Map<String, Object> aggregations = new LinkedHashMap<>();
+
+        aggregations.put(FACET_REPO, perRepo);
+
+        return aggregations;
+    }
+
+    private Map<String, Object> buildDayAggregation(String timezone) {
+        Map<String, Object> dateHistogram = new LinkedHashMap<>();
+
+        dateHistogram.put("field", "evtTime");
+        dateHistogram.put("calendar_interval", "1d");
+
+        ZoneId zoneId = auditMetricsHelper.parseZoneId(timezone);
+
+        if (zoneId != null) {
+            dateHistogram.put("time_zone", zoneId.getId());
+        }
+
+        return Map.of("per_day", Map.of("date_histogram", dateHistogram));
+    }
+
+    private Map<String, Object> buildHourAggregation(String timezone) {
+        Map<String, Object> dateHistogram = new LinkedHashMap<>();
+
+        dateHistogram.put("field", "evtTime");
+        dateHistogram.put("fixed_interval", "1h");
+
+        ZoneId zoneId = auditMetricsHelper.parseZoneId(timezone);
+
+        if (zoneId != null) {
+            dateHistogram.put("time_zone", zoneId.getId());
+        }
+
+        return Map.of("per_hour", Map.of("date_histogram", dateHistogram));
+    }
+
+    private JsonNode runMetricsSearch(Map<String, Object> queryBody, String 
context) {
+        RestClient client = openSearchMgr.getClient();
+
+        if (client == null) {
+            LOGGER.warn("OpenSearch client is null, so not running the 
query.");
+
+            throw restErrorUtil.createRESTException("Error connecting to 
search engine", MessageEnums.ERROR_SYSTEM);
+        }
+
+        JsonNode result;
+
+        try {
+            String  body    = MAPPER.writeValueAsString(queryBody);
+            Request request = new Request("POST", "/" + 
openSearchMgr.getIndex() + "/_search");
+
+            request.setEntity(new NStringEntity(body, 
ContentType.APPLICATION_JSON));
+
+            Response response = client.performRequest(request);
+
+            result = parseMetricsSearchResponse(response, context);
+        } catch (IOException e) {
+            LOGGER.warn("OpenSearch query failed for {}: {}", context, 
e.getMessage());
+
+            throw restErrorUtil.createRESTException("Error querying search 
engine", MessageEnums.ERROR_SYSTEM);
+        }
+
+        return result;
+    }
+
+    private JsonNode parseMetricsSearchResponse(Response response, String 
context) throws IOException {
+        int statusCode = response.getStatusLine().getStatusCode();
+
+        if (statusCode < 200 || statusCode >= 300) {
+            LOGGER.warn("OpenSearch query failed for {} with status {}", 
context, statusCode);
+
+            throw restErrorUtil.createRESTException("Error querying search 
engine", MessageEnums.ERROR_SYSTEM);
+        }
+
+        String json = EntityUtils.toString(response.getEntity());
+
+        return MAPPER.readTree(json);
+    }
+
+    private List<RangerAuditMetrics> extractAuditMetricsList(JsonNode 
response, SearchFilter filter) {
+        JsonNode buckets = response.at("/aggregations/per_repo/buckets");
+
+        if (!buckets.isArray()) {
+            return Collections.emptyList();
+        }
+
+        String serviceTypeFilter = filter != null ? 
filter.getParam(SearchFilter.SERVICE_TYPE) : null;
+        List<RangerAuditMetrics> metrics = new ArrayList<>();
+
+        for (JsonNode repoBucket : buckets) {
+            processRepoBucket(repoBucket, metrics, serviceTypeFilter);
+        }
+
+        return metrics;
+    }
+
+    private void processRepoBucket(JsonNode repoBucket, 
List<RangerAuditMetrics> metrics, String serviceTypeFilter) {
+        String serviceName = bucketKeyToString(repoBucket);
+
+        if (serviceName == null) {
+            return;
+        }
+
+        JsonNode agentBuckets = getSubBuckets(repoBucket, FACET_AGENT);
+
+        if (agentBuckets == null) {
+            
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, null, null, null, bucketDocCount(repoBucket)));
+        } else {
+            processAgentBuckets(agentBuckets, metrics, serviceTypeFilter, 
serviceName);
+        }
+    }
+
+    private void processAgentBuckets(JsonNode agentBuckets, 
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName) 
{
+        for (JsonNode agentBucket : agentBuckets) {
+            String appId = bucketKeyToString(agentBucket);
+            JsonNode cliIpBuckets = getSubBuckets(agentBucket, FACET_CLIIP);
+
+            if (cliIpBuckets == null) {
+                
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, appId, null, null, bucketDocCount(agentBucket)));
+            } else {
+                processCliIpBuckets(cliIpBuckets, metrics, serviceTypeFilter, 
serviceName, appId);
+            }
+        }
+    }
+
+    private void processCliIpBuckets(JsonNode cliIpBuckets, 
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName, 
String appId) {
+        for (JsonNode cliIpBucket : cliIpBuckets) {
+            String clientIP = bucketKeyToString(cliIpBucket);
+            JsonNode clusterBuckets = getSubBuckets(cliIpBucket, 
FACET_CLUSTER);
+
+            if (clusterBuckets == null) {
+                
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, appId, null, clientIP, bucketDocCount(cliIpBucket)));
+            } else {
+                processClusterBuckets(clusterBuckets, metrics, 
serviceTypeFilter, serviceName, appId, clientIP);
+            }
+        }
+    }
+
+    private void processClusterBuckets(JsonNode clusterBuckets, 
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName, 
String appId, String clientIP) {
+        for (JsonNode clusterBucket : clusterBuckets) {
+            String clusterName = bucketKeyToString(clusterBucket);
+
+            
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, appId, clusterName, clientIP, bucketDocCount(clusterBucket)));
+        }
+    }
+
+    private JsonNode getSubBuckets(JsonNode parentBucket, String aggName) {
+        JsonNode buckets = parentBucket.path(aggName).path("buckets");
+
+        if (!buckets.isArray() || buckets.isEmpty()) {
+            return null;
+        }
+
+        return buckets;
+    }
+
+    private String bucketKeyToString(JsonNode bucket) {
+        String ret = null;
+
+        if (bucket != null && bucket.has("key")) {
+            ret = bucket.get("key").asText(null);
+
+            if (StringUtils.isBlank(ret)) {
+                ret = null;
+            }
+        }
+
+        return ret;
+    }
+
+    private long bucketDocCount(JsonNode bucket) {
+        long ret = 0L;
+
+        if (bucket != null && bucket.has("doc_count")) {
+            ret = bucket.get("doc_count").asLong();
+        }
+
+        return ret;
+    }
+
+    private List<RangerAuditMetricsByDays> extractAuditMetricsByDays(JsonNode 
response, SearchFilter filter, String timezone) {
+        List<RangerAuditMetricsByDays> metrics = new ArrayList<>();
+        JsonNode                       buckets = 
response.at("/aggregations/per_day/buckets");
+
+        if (!buckets.isArray()) {
+            return Collections.emptyList();
+        }
+
+        FilterParams params = auditMetricsHelper.getFilterParams(filter);
+
+        for (JsonNode bucket : buckets) {
+            Long auditDate = parseBucketTime(bucket, timezone);
+
+            if (auditDate == null) {
+                continue;
+            }
+
+            metrics.add(auditMetricsHelper.buildAuditMetricsByDays(params, 
auditDate, bucket.get("doc_count").asLong()));
+        }
+
+        return metrics;
+    }
+
+    private List<RangerAuditMetricsByHours> 
extractAuditMetricsByHours(JsonNode response, SearchFilter filter, String 
timezone) {
+        List<RangerAuditMetricsByHours> metrics = new ArrayList<>();
+        JsonNode                        buckets = 
response.at("/aggregations/per_hour/buckets");
+
+        if (!buckets.isArray()) {
+            return Collections.emptyList();
+        }
+
+        FilterParams params = auditMetricsHelper.getFilterParams(filter);
+        ZoneId         zoneId = auditMetricsHelper.resolveZoneId(timezone);
+
+        for (JsonNode bucket : buckets) {
+            Long auditDate = parseBucketTime(bucket, timezone);
+
+            if (auditDate == null) {
+                continue;
+            }
+
+            ZonedDateTime dateTime = 
ZonedDateTime.ofInstant(Instant.ofEpochMilli(auditDate), zoneId);
+            int           hour     = dateTime.getHour();
+
+            metrics.add(auditMetricsHelper.buildAuditMetricsByHours(params, 
hour, bucket.get("doc_count").asLong()));
+        }
+
+        return metrics;
+    }
+
+    private Long parseBucketTime(JsonNode bucket, String timezone) {
+        Long result = null;
+
+        if (bucket != null) {
+            String keyAsString = bucket.get("key_as_string").asText(null);
+
+            if (keyAsString == null) {
+                keyAsString = bucket.get("key").asText(null);
+            }
+
+            if (keyAsString != null) {
+                result = auditMetricsHelper.parseAuditDate(keyAsString);
+            }
+        }
+
+        return result;
+    }
+}
diff --git 
a/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java 
b/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java
index 8a992b88a..44c916d6d 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/AuditMetricsREST.java
@@ -20,6 +20,8 @@
 package org.apache.ranger.rest;
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsServiceFactory;
 import org.apache.ranger.authorization.hadoop.config.RangerAdminConfig;
 import org.apache.ranger.common.MessageEnums;
 import org.apache.ranger.common.RESTErrorUtil;
@@ -29,7 +31,6 @@
 import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
 import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.security.context.RangerAPIList;
-import org.apache.ranger.solr.SolrAccessAuditsService;
 import org.apache.ranger.view.RangerAuditMetricsList;
 import org.apache.ranger.view.RangerAuditMetricsListByDays;
 import org.apache.ranger.view.RangerAuditMetricsListByHours;
@@ -73,7 +74,7 @@ public class AuditMetricsREST {
     RangerSearchUtil searchUtil;
 
     @Autowired
-    SolrAccessAuditsService solrAccessAuditsService;
+    AccessAuditsMetricsServiceFactory accessAuditsMetricsServiceFactory;
 
     @GET
     @Path("/metrics/servicetype/{servicetype}/servicename/{servicename}")
@@ -84,7 +85,9 @@ public RangerAuditMetrics 
getLatestAuditMetrics(@PathParam("servicetype") String
         LOG.debug("==> AuditMetricsREST.getLatestAuditMetrics(serviceType={} 
serviceName={})", serviceType, serviceName);
         RangerAuditMetrics ret;
         try {
-            ret = solrAccessAuditsService.getLatestAuditMetrics(serviceType, 
serviceName, timezone);
+            AccessAuditsMetricsService accessAuditsMetricsService = 
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+            ret = 
accessAuditsMetricsService.getLatestAuditMetrics(serviceType, serviceName, 
timezone);
         } catch (WebApplicationException excp) {
             throw excp;
         } catch (Throwable excp) {
@@ -104,7 +107,9 @@ public RangerAuditMetrics getAuditMetrics(@PathParam("id") 
Long id, @QueryParam(
         LOG.debug("==> AuditMetricsREST.getAuditMetrics(id={})", id);
         RangerAuditMetrics ret;
         try {
-            ret = solrAccessAuditsService.getAuditMetrics(id, timezone);
+            AccessAuditsMetricsService accessAuditsMetricsService = 
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+            ret = accessAuditsMetricsService.getAuditMetrics(id, timezone);
         } catch (WebApplicationException excp) {
             throw excp;
         } catch (Throwable excp) {
@@ -128,7 +133,9 @@ public RangerAuditMetricsList 
getAllLatestRangerAuditMetrics(@Context HttpServle
         SearchFilter filter = searchUtil.getSearchFilter(request, 
Collections.emptyList());
 
         try {
-            rangerAuditMetrics = 
solrAccessAuditsService.getLatestAuditMetricsList(filter, timezone);
+            AccessAuditsMetricsService accessAuditsMetricsService = 
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+            rangerAuditMetrics = 
accessAuditsMetricsService.getLatestAuditMetricsList(filter, timezone);
         } catch (WebApplicationException excp) {
             throw excp;
         } catch (Throwable excp) {
@@ -156,7 +163,9 @@ public RangerAuditMetricsListByHours 
getDailyAuditMetrics(@Context HttpServletRe
 
         SearchFilter filter = searchUtil.getSearchFilter(request, 
Collections.emptyList());
         try {
-            rangerAuditMetricsByHours = 
solrAccessAuditsService.getAuditMetricsByHours(filter, timezone);
+            AccessAuditsMetricsService accessAuditsMetricsService = 
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+            rangerAuditMetricsByHours = 
accessAuditsMetricsService.getAuditMetricsByHours(filter, timezone);
         } catch (WebApplicationException excp) {
             throw excp;
         } catch (Throwable excp) {
@@ -191,7 +200,9 @@ public RangerAuditMetricsListByDays 
getDaysAuditMetrics(@Context HttpServletRequ
         List<RangerAuditMetricsByDays> rangerAuditMetricsByDays;
         SearchFilter                   filter = 
searchUtil.getSearchFilter(request, Collections.emptyList());
         try {
-            rangerAuditMetricsByDays = 
solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays, filter, 
timezone);
+            AccessAuditsMetricsService accessAuditsMetricsService = 
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+            rangerAuditMetricsByDays = 
accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays, filter, 
timezone);
         } catch (WebApplicationException excp) {
             throw excp;
         } catch (Throwable excp) {
diff --git 
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
 
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
index 4e6a8510e..701b86a0f 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java
@@ -20,6 +20,7 @@
 package org.apache.ranger.solr;
 
 import org.apache.ranger.AccessAuditsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
 import org.apache.ranger.audit.provider.MiscUtil;
 import org.apache.ranger.common.MessageEnums;
 import org.apache.ranger.common.PropertiesUtil;
@@ -51,7 +52,7 @@
 
 @Service
 @Scope("singleton")
-public class SolrAccessAuditsService extends AccessAuditsService {
+public class SolrAccessAuditsService extends AccessAuditsService implements 
AccessAuditsMetricsService {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(SolrAccessAuditsService.class);
 
     @Autowired
diff --git 
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
 
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
index f926b6d26..f73319ee5 100644
--- 
a/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
+++ 
b/security-admin/src/main/java/org/apache/ranger/solr/SolrAuditMetricsHelper.java
@@ -20,11 +20,11 @@
 package org.apache.ranger.solr;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper.FilterParams;
 import org.apache.ranger.common.MessageEnums;
 import org.apache.ranger.common.RESTErrorUtil;
-import org.apache.ranger.db.RangerDaoManager;
 import org.apache.ranger.entity.XXService;
-import org.apache.ranger.entity.XXServiceDef;
 import org.apache.ranger.plugin.model.RangerAuditMetrics;
 import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
 import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
@@ -39,23 +39,17 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.time.DateTimeException;
 import java.time.Instant;
 import java.time.ZoneId;
-import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
-import java.time.format.DateTimeParseException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Date;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 
 @Component
 public class SolrAuditMetricsHelper {
     private static final Logger LOGGER = 
LoggerFactory.getLogger(SolrAuditMetricsHelper.class);
-    private static final long   MISSING_REPO_TYPE_SENTINEL = -1L;
 
     private static final String FACET_REPO = "per_repo";
     private static final String FACET_AGENT = "per_agent";
@@ -64,8 +58,6 @@ public class SolrAuditMetricsHelper {
     private static final String BUCKET_VAL = "val";
     private static final String FACETS_KEY = "facets";
 
-    private final Map<String, Long> repoTypeByServiceType = new 
ConcurrentHashMap<>();
-
     @Autowired
     SolrMgr solrMgr;
 
@@ -76,10 +68,10 @@ public class SolrAuditMetricsHelper {
     RESTErrorUtil restErrorUtil;
 
     @Autowired
-    RangerDaoManager daoManager;
+    AuditMetricsHelper auditMetricsHelper;
 
     public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String 
serviceName, String timezone) {
-        SearchFilter filter = buildSearchFilter(serviceType, serviceName, 
null, null, null);
+        SearchFilter filter = 
auditMetricsHelper.buildSearchFilter(serviceType, serviceName, null, null, 
null);
 
         SolrQuery query = buildMetricsQuery();
         applyAuditMetricsFilters(query, filter);
@@ -88,7 +80,7 @@ public RangerAuditMetrics getLatestAuditMetrics(String 
serviceType, String servi
 
         QueryResponse response = runMetricsQuery(query, "latest audit 
metrics");
         long count = response.getResults() != null ? 
response.getResults().getNumFound() : 0L;
-        return buildAuditMetrics(serviceType, serviceName, null, null, null, 
count);
+        return auditMetricsHelper.buildAuditMetrics(serviceType, serviceName, 
null, null, null, count);
     }
 
     public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter 
filter, String timezone) {
@@ -124,16 +116,7 @@ public List<RangerAuditMetricsByHours> 
getAuditMetricsByHours(SearchFilter filte
     }
 
     public String resolveServiceType(XXService service) {
-        String ret = null;
-
-        if (service != null && daoManager != null && 
daoManager.getXXServiceDef() != null) {
-            XXServiceDef serviceDef = 
daoManager.getXXServiceDef().getById(service.getType());
-            if (serviceDef != null) {
-                ret = serviceDef.getName();
-            }
-        }
-
-        return ret;
+        return auditMetricsHelper.resolveServiceType(service);
     }
 
     private SolrQuery buildMetricsQuery() {
@@ -167,7 +150,6 @@ private QueryResponse runMetricsQuery(SolrQuery query, 
String context) {
     }
 
     private String buildAuditAccessMetricsFacet(int olderThanInDays) {
-        // If olderThanInDays is 7, we go back 6 days from today to include 
today
         int daysBack = olderThanInDays - 1;
 
         return 
String.format("{per_day:{type:range,field:evtTime,start:\"NOW-%dDAYS/DAY\",end:\"NOW\",gap:\"+1DAY\",mincount:1}}",
 daysBack);
@@ -201,16 +183,6 @@ private void addTodayMetricsRangeFilter(SolrQuery query) {
         query.addFilterQuery("evtTime:[NOW/DAY TO NOW]");
     }
 
-    private SearchFilter buildSearchFilter(String serviceType, String 
serviceName, String appId, String clusterName, String clientIP) {
-        SearchFilter filter = new SearchFilter();
-        filter.setParam(SearchFilter.SERVICE_TYPE, serviceType);
-        filter.setParam(SearchFilter.SERVICE_NAME, serviceName);
-        filter.setParam(SearchFilter.PLUGIN_APP_ID, appId);
-        filter.setParam(SearchFilter.CLUSTER_NAME, clusterName);
-        filter.setParam(SearchFilter.CLIENT_IP, clientIP);
-        return filter;
-    }
-
     private void applyAuditMetricsFilters(SolrQuery query, SearchFilter 
filter) {
         if (query == null || filter == null) {
             return;
@@ -221,8 +193,8 @@ private void applyAuditMetricsFilters(SolrQuery query, 
SearchFilter filter) {
 
         String serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
         if (StringUtils.isNotBlank(serviceType)) {
-            long repoType = resolveRepoType(serviceType);
-            if (repoType == MISSING_REPO_TYPE_SENTINEL) {
+            long repoType = auditMetricsHelper.resolveRepoType(serviceType);
+            if (repoType == AuditMetricsHelper.MISSING_REPO_TYPE_SENTINEL) {
                 query.addFilterQuery("repoType:-1");
             } else {
                 query.addFilterQuery("repoType:" + repoType);
@@ -249,35 +221,13 @@ private void applyTimezone(SolrQuery query, String 
timezone) {
         }
 
         String tz = timezone.trim();
-        try {
-            ZoneId.of(tz);
-            query.set("TZ", tz);
-        } catch (DateTimeException e) {
-            query.set("TZ", "UTC");
-        }
-    }
+        ZoneId zoneId = auditMetricsHelper.parseZoneId(tz);
 
-    private long resolveRepoType(String serviceType) {
-        if (StringUtils.isBlank(serviceType)) {
-            return MISSING_REPO_TYPE_SENTINEL;
-        }
-
-        String cacheKey = serviceType.trim().toLowerCase();
-        Long cached = repoTypeByServiceType.get(cacheKey);
-        if (cached != null) {
-            return cached;
-        }
-
-        long resolved = MISSING_REPO_TYPE_SENTINEL;
-        if (daoManager != null && daoManager.getXXServiceDef() != null) {
-            XXServiceDef serviceDef = 
daoManager.getXXServiceDef().findByName(serviceType);
-            if (serviceDef != null && serviceDef.getId() != null) {
-                resolved = serviceDef.getId();
-            }
+        if (zoneId != null) {
+            query.set("TZ", zoneId.getId());
+        } else {
+            query.set("TZ", "UTC");
         }
-
-        repoTypeByServiceType.put(cacheKey, resolved);
-        return resolved;
     }
 
     private List<RangerAuditMetrics> extractAuditMetricsList(QueryResponse 
response, SearchFilter filter) {
@@ -312,7 +262,7 @@ private void processRepoBuckets(List<?> repoBuckets, 
List<RangerAuditMetrics> me
             List<?> agentBuckets = extractBuckets(getBucketValue(repoBucket, 
FACET_AGENT));
 
             if (agentBuckets == null || agentBuckets.isEmpty()) {
-                metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName, 
null, null, null, bucketCount(repoBucket)));
+                
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, null, null, null, bucketCount(repoBucket)));
             } else {
                 processAgentBuckets(agentBuckets, metrics, serviceTypeFilter, 
serviceName);
             }
@@ -326,7 +276,7 @@ private void processAgentBuckets(List<?> agentBuckets, 
List<RangerAuditMetrics>
             List<?> cliIpBuckets = extractBuckets(getBucketValue(agentBucket, 
FACET_CLIIP));
 
             if (cliIpBuckets == null || cliIpBuckets.isEmpty()) {
-                metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName, 
appId, null, null, bucketCount(agentBucket)));
+                
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, appId, null, null, bucketCount(agentBucket)));
             } else {
                 processCliIpBuckets(cliIpBuckets, metrics, serviceTypeFilter, 
serviceName, appId);
             }
@@ -339,7 +289,7 @@ private void processCliIpBuckets(List<?> cliIpBuckets, 
List<RangerAuditMetrics>
             List<?> clusterBuckets = 
extractBuckets(getBucketValue(cliIpBucket, FACET_CLUSTER));
 
             if (clusterBuckets == null || clusterBuckets.isEmpty()) {
-                metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName, 
appId, null, clientIP, bucketCount(cliIpBucket)));
+                
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, appId, null, clientIP, bucketCount(cliIpBucket)));
             } else {
                 processClusterBuckets(clusterBuckets, metrics, 
serviceTypeFilter, serviceName, appId, clientIP);
             }
@@ -349,7 +299,7 @@ private void processCliIpBuckets(List<?> cliIpBuckets, 
List<RangerAuditMetrics>
     private void processClusterBuckets(List<?> clusterBuckets, 
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName, 
String appId, String clientIP) {
         for (Object clusterBucket : clusterBuckets) {
             String clusterName = 
bucketValToString(getBucketValue(clusterBucket, BUCKET_VAL));
-            metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName, 
appId, clusterName, clientIP, bucketCount(clusterBucket)));
+            
metrics.add(auditMetricsHelper.buildAuditMetrics(serviceTypeFilter, 
serviceName, appId, clusterName, clientIP, bucketCount(clusterBucket)));
         }
     }
 
@@ -371,51 +321,6 @@ private String bucketValToString(Object value) {
         return ret;
     }
 
-    private RangerAuditMetrics buildAuditMetrics(String serviceType, String 
serviceName, String appId, String clusterName, String clientIP, long count) {
-        RangerAuditMetrics metric = new RangerAuditMetrics();
-        metric.setServiceName(serviceName);
-        metric.setServiceType(resolveServiceType(serviceType, serviceName));
-        metric.setAppId(appId);
-        metric.setClusterName(clusterName);
-        metric.setClientIP(clientIP);
-        metric.setNumberOfAudits(count);
-
-        Long serviceId = resolveServiceId(serviceName);
-        if (serviceId != null) {
-            metric.setId(serviceId);
-        }
-
-        return metric;
-    }
-
-    private Long resolveServiceId(String serviceName) {
-        Long ret = null;
-
-        if (StringUtils.isNotBlank(serviceName) && daoManager != null && 
daoManager.getXXService() != null) {
-            XXService service = 
daoManager.getXXService().findByName(serviceName);
-            if (service != null) {
-                ret = service.getId();
-            }
-        }
-
-        return ret;
-    }
-
-    private String resolveServiceType(String serviceType, String serviceName) {
-        String ret = serviceType;
-
-        if (StringUtils.isBlank(ret)) {
-            if (StringUtils.isNotBlank(serviceName) && daoManager != null && 
daoManager.getXXService() != null) {
-                XXService service = 
daoManager.getXXService().findByName(serviceName);
-                ret = resolveServiceType(service);
-            } else {
-                ret = null;
-            }
-        }
-
-        return ret;
-    }
-
     private List<RangerAuditMetricsByDays> 
extractAuditMetricsByDays(QueryResponse response, SearchFilter filter) {
         NamedList<Object> responseList = response.getResponse();
         if (responseList == null) {
@@ -436,15 +341,11 @@ private List<RangerAuditMetricsByDays> 
extractAuditMetricsByDays(QueryResponse r
         }
 
         List<RangerAuditMetricsByDays> metrics = new ArrayList<>();
-        String serviceType = filter != null ? 
filter.getParam(SearchFilter.SERVICE_TYPE) : null;
-        String serviceName = filter != null ? 
filter.getParam(SearchFilter.SERVICE_NAME) : null;
-        String appId = filter != null ? 
filter.getParam(SearchFilter.PLUGIN_APP_ID) : null;
-        String clusterName = filter != null ? 
filter.getParam(SearchFilter.CLUSTER_NAME) : null;
-        String clientIP = filter != null ? 
filter.getParam(SearchFilter.CLIENT_IP) : null;
+        FilterParams params = auditMetricsHelper.getFilterParams(filter);
 
         for (Object bucketObj : buckets) {
             Object dateValue = getBucketValue(bucketObj, BUCKET_VAL);
-            Long auditDate = parseAuditDate(dateValue);
+            Long auditDate = auditMetricsHelper.parseAuditDate(dateValue);
             if (auditDate == null) {
                 continue;
             }
@@ -452,8 +353,7 @@ private List<RangerAuditMetricsByDays> 
extractAuditMetricsByDays(QueryResponse r
             Object countObj = getBucketValue(bucketObj, "count");
             long count = countObj instanceof Number ? ((Number) 
countObj).longValue() : 0L;
 
-            RangerAuditMetricsByDays metric = new 
RangerAuditMetricsByDays(serviceType, serviceName, appId, clusterName, 
clientIP, auditDate, count);
-            metrics.add(metric);
+            metrics.add(auditMetricsHelper.buildAuditMetricsByDays(params, 
auditDate, count));
         }
 
         return metrics;
@@ -479,15 +379,12 @@ private List<RangerAuditMetricsByHours> 
extractAuditMetricsByHours(QueryResponse
         }
 
         List<RangerAuditMetricsByHours> metrics = new ArrayList<>();
-        String serviceType = filter != null ? 
filter.getParam(SearchFilter.SERVICE_TYPE) : null;
-        String serviceName = filter != null ? 
filter.getParam(SearchFilter.SERVICE_NAME) : null;
-        String appId = filter != null ? 
filter.getParam(SearchFilter.PLUGIN_APP_ID) : null;
-        String clusterName = filter != null ? 
filter.getParam(SearchFilter.CLUSTER_NAME) : null;
-        String clientIP = filter != null ? 
filter.getParam(SearchFilter.CLIENT_IP) : null;
+        FilterParams params = auditMetricsHelper.getFilterParams(filter);
+        ZoneId zoneId = auditMetricsHelper.resolveZoneId(timezone);
 
         for (Object bucketObj : buckets) {
             Object dateValue = getBucketValue(bucketObj, BUCKET_VAL);
-            Long auditDate = parseAuditDate(dateValue);
+            Long auditDate = auditMetricsHelper.parseAuditDate(dateValue);
             if (auditDate == null) {
                 continue;
             }
@@ -495,31 +392,15 @@ private List<RangerAuditMetricsByHours> 
extractAuditMetricsByHours(QueryResponse
             Object countObj = getBucketValue(bucketObj, "count");
             long count = countObj instanceof Number ? ((Number) 
countObj).longValue() : 0L;
 
-            ZoneId zoneId = resolveZoneId(timezone);
             ZonedDateTime dateTime = 
ZonedDateTime.ofInstant(Instant.ofEpochMilli(auditDate), zoneId);
             int hour = dateTime.getHour();
 
-            RangerAuditMetricsByHours metric = new 
RangerAuditMetricsByHours(serviceType, serviceName, appId, clusterName, 
clientIP, hour, count);
-            metrics.add(metric);
+            metrics.add(auditMetricsHelper.buildAuditMetricsByHours(params, 
hour, count));
         }
 
         return metrics;
     }
 
-    private ZoneId resolveZoneId(String timezone) {
-        ZoneId ret = ZoneOffset.UTC;
-
-        if (StringUtils.isNotBlank(timezone)) {
-            try {
-                ret = ZoneId.of(timezone.trim());
-            } catch (DateTimeException e) {
-                LOGGER.warn("Invalid timezone '{}', using UTC", timezone, e);
-            }
-        }
-
-        return ret;
-    }
-
     private List<?> extractBuckets(Object perDayObj) {
         List<?> ret = Collections.emptyList();
 
@@ -549,22 +430,4 @@ private Object getBucketValue(Object bucketObj, String 
key) {
 
         return ret;
     }
-
-    private Long parseAuditDate(Object value) {
-        Long ret = null;
-
-        if (value instanceof Date) {
-            ret = ((Date) value).getTime();
-        } else if (value instanceof Number) {
-            ret = ((Number) value).longValue();
-        } else if (value instanceof String) {
-            try {
-                ret = Instant.parse((String) value).toEpochMilli();
-            } catch (DateTimeParseException e) {
-                LOGGER.warn("Unable to parse audit metric date value: {}", 
value, e);
-            }
-        }
-
-        return ret;
-    }
 }
diff --git 
a/security-admin/src/test/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactoryTest.java
 
b/security-admin/src/test/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactoryTest.java
new file mode 100644
index 000000000..a4ded6739
--- /dev/null
+++ 
b/security-admin/src/test/java/org/apache/ranger/audit/metrics/AccessAuditsMetricsServiceFactoryTest.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.audit.metrics;
+
+import org.apache.ranger.biz.RangerBizUtil;
+import org.apache.ranger.opensearch.OpenSearchAccessAuditsService;
+import org.apache.ranger.solr.SolrAccessAuditsService;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class AccessAuditsMetricsServiceFactoryTest {
+    @Mock
+    RangerBizUtil rangerBizUtil;
+
+    @Mock
+    SolrAccessAuditsService solrAccessAuditsService;
+
+    @Mock
+    OpenSearchAccessAuditsService openSearchAccessAuditsService;
+
+    @InjectMocks
+    AccessAuditsMetricsServiceFactory accessAuditsMetricsServiceFactory;
+
+    @BeforeEach
+    void setUp() {
+        
when(rangerBizUtil.getAuditDBType()).thenReturn(RangerBizUtil.AUDIT_STORE_SOLR);
+    }
+
+    @Test
+    void getAccessAuditsMetricsService_returnsSolrByDefault() {
+        AccessAuditsMetricsService service = 
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+        assertSame(solrAccessAuditsService, service);
+    }
+
+    @Test
+    void getAccessAuditsMetricsService_returnsOpenSearchWhenConfigured() {
+        
when(rangerBizUtil.getAuditDBType()).thenReturn(RangerBizUtil.AUDIT_STORE_OPENSEARCH);
+
+        AccessAuditsMetricsService service = 
accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService();
+
+        assertSame(openSearchAccessAuditsService, service);
+    }
+}
diff --git 
a/security-admin/src/test/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelperTest.java
 
b/security-admin/src/test/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelperTest.java
new file mode 100644
index 000000000..ae8a355b9
--- /dev/null
+++ 
b/security-admin/src/test/java/org/apache/ranger/opensearch/OpenSearchAuditMetricsHelperTest.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.opensearch;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.StatusLine;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
+import org.apache.ranger.common.RESTErrorUtil;
+import org.apache.ranger.db.RangerDaoManager;
+import org.apache.ranger.db.XXServiceDao;
+import org.apache.ranger.db.XXServiceDefDao;
+import org.apache.ranger.entity.XXService;
+import org.apache.ranger.entity.XXServiceDef;
+import org.apache.ranger.plugin.model.RangerAuditMetrics;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
+import org.apache.ranger.plugin.util.SearchFilter;
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestClient;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.ws.rs.WebApplicationException;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class OpenSearchAuditMetricsHelperTest {
+    @Test
+    void getLatestAuditMetrics_returnsCount() throws Exception {
+        OpenSearchAuditMetricsHelper helper = 
createHelperWithServiceId("dev_hdfs", 1L);
+        stubOpenSearchResponse(helper, 
"{\"hits\":{\"total\":{\"value\":42}}}", 200);
+
+        RangerAuditMetrics metrics = helper.getLatestAuditMetrics("hdfs", 
"dev_hdfs", null);
+
+        assertEquals("dev_hdfs", metrics.getServiceName());
+        assertEquals("hdfs", metrics.getServiceType());
+        assertEquals(42L, metrics.getNumberOfAudits());
+    }
+
+    @Test
+    void getLatestAuditMetrics_whenClientNull_throws() {
+        OpenSearchAuditMetricsHelper helper = new 
OpenSearchAuditMetricsHelper();
+        helper.openSearchMgr = mock(OpenSearchMgr.class);
+        helper.restErrorUtil = new RESTErrorUtil();
+        helper.auditMetricsHelper = new AuditMetricsHelper();
+
+        when(helper.openSearchMgr.getClient()).thenReturn(null);
+
+        assertThrows(WebApplicationException.class, () -> 
helper.getLatestAuditMetrics("hdfs", "dev_hdfs", null));
+    }
+
+    @Test
+    void getLatestAuditMetrics_whenHttpError_throws() throws Exception {
+        OpenSearchAuditMetricsHelper helper = createHelper();
+        stubOpenSearchErrorResponse(helper, 400);
+
+        assertThrows(WebApplicationException.class, () -> 
helper.getLatestAuditMetrics("hdfs", "dev_hdfs", null));
+    }
+
+    @Test
+    void getLatestAuditMetricsList_includesAgentCliIpAndCluster() throws 
Exception {
+        OpenSearchAuditMetricsHelper helper = createHelperWithDao("dev_hdfs", 
1L, "hdfs", 10L);
+        stubOpenSearchResponse(helper, buildNestedMetricsResponse("dev_hdfs", 
"hdfs", "172.18.0.16", "ABC cluster", 7L), 200);
+
+        List<RangerAuditMetrics> metrics = 
helper.getLatestAuditMetricsList(new SearchFilter(), null);
+
+        assertEquals(1, metrics.size());
+        RangerAuditMetrics metric = metrics.get(0);
+        assertEquals("dev_hdfs", metric.getServiceName());
+        assertEquals("hdfs", metric.getAppId());
+        assertEquals("172.18.0.16", metric.getClientIP());
+        assertEquals("ABC cluster", metric.getClusterName());
+        assertEquals(7L, metric.getNumberOfAudits());
+        assertEquals(1L, metric.getId());
+    }
+
+    @Test
+    void getLatestAuditMetricsList_missingAgent_omitsAppId() throws Exception {
+        OpenSearchAuditMetricsHelper helper = createHelperWithDao("dev_hdfs", 
1L, "hdfs", 10L);
+        stubOpenSearchResponse(helper, buildNestedMetricsResponse("dev_hdfs", 
"", "172.18.0.16", "ABC cluster", 5L), 200);
+
+        List<RangerAuditMetrics> metrics = 
helper.getLatestAuditMetricsList(new SearchFilter(), null);
+
+        assertEquals(1, metrics.size());
+        assertNull(metrics.get(0).getAppId());
+        assertEquals("172.18.0.16", metrics.get(0).getClientIP());
+        assertEquals("ABC cluster", metrics.get(0).getClusterName());
+        assertEquals(5L, metrics.get(0).getNumberOfAudits());
+    }
+
+    @Test
+    void getAuditMetricsByDays_returnsDailyBuckets() throws Exception {
+        OpenSearchAuditMetricsHelper helper = createHelper();
+        stubOpenSearchResponse(helper,
+                
"{\"aggregations\":{\"per_day\":{\"buckets\":[{\"key_as_string\":\"2026-08-11T00:00:00.000Z\",\"doc_count\":25}]}}}",
+                200);
+
+        SearchFilter filter = new SearchFilter();
+        filter.setParam(SearchFilter.SERVICE_NAME, "dev_hdfs");
+        filter.setParam(SearchFilter.SERVICE_TYPE, "hdfs");
+
+        List<RangerAuditMetricsByDays> metrics = 
helper.getAuditMetricsByDays(7, filter, "UTC");
+
+        assertEquals(1, metrics.size());
+        assertEquals(25L, metrics.get(0).getNumberOfAudits());
+        assertEquals("dev_hdfs", metrics.get(0).getServiceName());
+        assertEquals("hdfs", metrics.get(0).getServiceType());
+    }
+
+    @Test
+    void getAuditMetricsByHours_returnsHourlyBuckets() throws Exception {
+        OpenSearchAuditMetricsHelper helper = createHelper();
+        stubOpenSearchResponse(helper,
+                
"{\"aggregations\":{\"per_hour\":{\"buckets\":[{\"key_as_string\":\"2026-08-11T12:00:00.000Z\",\"doc_count\":15}]}}}",
+                200);
+
+        List<RangerAuditMetricsByHours> metrics = 
helper.getAuditMetricsByHours(new SearchFilter(), "UTC");
+
+        assertEquals(1, metrics.size());
+        assertEquals(12, metrics.get(0).getHours());
+        assertEquals(15L, metrics.get(0).getNumberOfAudits());
+    }
+
+    private OpenSearchAuditMetricsHelper createHelper() {
+        OpenSearchAuditMetricsHelper helper = new 
OpenSearchAuditMetricsHelper();
+        helper.openSearchMgr = mock(OpenSearchMgr.class);
+        helper.restErrorUtil = new RESTErrorUtil();
+        helper.auditMetricsHelper = new AuditMetricsHelper();
+
+        return helper;
+    }
+
+    private OpenSearchAuditMetricsHelper createHelperWithServiceId(String 
serviceName, Long serviceId) throws Exception {
+        RangerDaoManager daoManager = mock(RangerDaoManager.class);
+        XXServiceDao svcDao = mock(XXServiceDao.class);
+        XXService xxService = mock(XXService.class);
+
+        when(daoManager.getXXService()).thenReturn(svcDao);
+        when(svcDao.findByName(serviceName)).thenReturn(xxService);
+        when(xxService.getId()).thenReturn(serviceId);
+
+        return injectDaoManager(createHelper(), daoManager);
+    }
+
+    private OpenSearchAuditMetricsHelper createHelperWithDao(String 
serviceName, Long serviceId, String serviceType, Long serviceDefId) throws 
Exception {
+        RangerDaoManager daoManager = mock(RangerDaoManager.class);
+        XXServiceDao svcDao = mock(XXServiceDao.class);
+        XXServiceDefDao sdDao = mock(XXServiceDefDao.class);
+        XXService xxService = mock(XXService.class);
+        XXServiceDef sd = mock(XXServiceDef.class);
+
+        when(daoManager.getXXService()).thenReturn(svcDao);
+        when(daoManager.getXXServiceDef()).thenReturn(sdDao);
+        when(svcDao.findByName(serviceName)).thenReturn(xxService);
+        when(xxService.getId()).thenReturn(serviceId);
+        when(xxService.getType()).thenReturn(serviceDefId);
+        when(sdDao.getById(serviceDefId)).thenReturn(sd);
+        when(sd.getName()).thenReturn(serviceType);
+
+        return injectDaoManager(createHelper(), daoManager);
+    }
+
+    private OpenSearchAuditMetricsHelper 
injectDaoManager(OpenSearchAuditMetricsHelper helper, RangerDaoManager 
daoManager) throws Exception {
+        java.lang.reflect.Field daoField = 
AuditMetricsHelper.class.getDeclaredField("daoManager");
+
+        daoField.setAccessible(true);
+        daoField.set(helper.auditMetricsHelper, daoManager);
+
+        return helper;
+    }
+
+    private void stubOpenSearchResponse(OpenSearchAuditMetricsHelper helper, 
String json, int statusCode) throws Exception {
+        RestClient client = mock(RestClient.class);
+        Response response = mock(Response.class);
+        StatusLine statusLine = mock(StatusLine.class);
+        HttpEntity entity = mock(HttpEntity.class);
+
+        when(helper.openSearchMgr.getClient()).thenReturn(client);
+        when(helper.openSearchMgr.getIndex()).thenReturn("ranger_audits");
+        when(client.performRequest(any(Request.class))).thenReturn(response);
+        when(response.getStatusLine()).thenReturn(statusLine);
+        when(statusLine.getStatusCode()).thenReturn(statusCode);
+        when(response.getEntity()).thenReturn(entity);
+        when(entity.getContent()).thenReturn(new 
ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)));
+    }
+
+    private void stubOpenSearchErrorResponse(OpenSearchAuditMetricsHelper 
helper, int statusCode) throws Exception {
+        RestClient client = mock(RestClient.class);
+        Response response = mock(Response.class);
+        StatusLine statusLine = mock(StatusLine.class);
+
+        when(helper.openSearchMgr.getClient()).thenReturn(client);
+        when(helper.openSearchMgr.getIndex()).thenReturn("ranger_audits");
+        when(client.performRequest(any(Request.class))).thenReturn(response);
+        when(response.getStatusLine()).thenReturn(statusLine);
+        when(statusLine.getStatusCode()).thenReturn(statusCode);
+    }
+
+    private String buildNestedMetricsResponse(String serviceName, String 
appId, String clientIP, String clusterName, long count) {
+        return "{"
+                + "\"aggregations\":{"
+                + "\"per_repo\":{\"buckets\":[{\"key\":\"" + serviceName + 
"\",\"doc_count\":" + count + ","
+                + "\"per_agent\":{\"buckets\":[{\"key\":\"" + appId + 
"\",\"doc_count\":" + count + ","
+                + "\"per_cliip\":{\"buckets\":[{\"key\":\"" + clientIP + 
"\",\"doc_count\":" + count + ","
+                + "\"per_cluster\":{\"buckets\":[{\"key\":\"" + clusterName + 
"\",\"doc_count\":" + count + "}]"
+                + "}}]}}]}}]}"
+                + "}}";
+    }
+}
diff --git 
a/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java 
b/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java
index bf31dfcb3..724b2a400 100644
--- 
a/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java
+++ 
b/security-admin/src/test/java/org/apache/ranger/rest/TestAuditMetricsREST.java
@@ -19,6 +19,8 @@
 
 package org.apache.ranger.rest;
 
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsService;
+import org.apache.ranger.audit.metrics.AccessAuditsMetricsServiceFactory;
 import org.apache.ranger.common.MessageEnums;
 import org.apache.ranger.common.RESTErrorUtil;
 import org.apache.ranger.common.RangerSearchUtil;
@@ -26,7 +28,6 @@
 import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
 import org.apache.ranger.plugin.model.RangerAuditMetricsByHours;
 import org.apache.ranger.plugin.util.SearchFilter;
-import org.apache.ranger.solr.SolrAccessAuditsService;
 import org.apache.ranger.view.RangerAuditMetricsList;
 import org.apache.ranger.view.RangerAuditMetricsListByDays;
 import org.apache.ranger.view.RangerAuditMetricsListByHours;
@@ -53,6 +54,7 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.contains;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -72,7 +74,10 @@ class TestAuditMetricsREST {
     RangerSearchUtil searchUtil;
 
     @Mock
-    SolrAccessAuditsService solrAccessAuditsService;
+    AccessAuditsMetricsServiceFactory accessAuditsMetricsServiceFactory;
+
+    @Mock
+    AccessAuditsMetricsService accessAuditsMetricsService;
 
     @Mock
     HttpServletRequest httpServletRequest;
@@ -91,6 +96,7 @@ void setUp() {
         testAuditMetricsByHours = createTestAuditMetricsByHours();
         testAuditMetricsByDays = createTestAuditMetricsByDays();
         testSearchFilter = new SearchFilter();
+        
lenient().when(accessAuditsMetricsServiceFactory.getAccessAuditsMetricsService()).thenReturn(accessAuditsMetricsService);
     }
 
     @Test
@@ -98,7 +104,7 @@ void testGetLatestAuditMetrics_Success() {
         String serviceType = "hive";
         String serviceName = "test-service";
         String timezone = "Asia/Kolkata";
-        when(solrAccessAuditsService.getLatestAuditMetrics(serviceType, 
serviceName, timezone)).thenReturn(testAuditMetrics);
+        when(accessAuditsMetricsService.getLatestAuditMetrics(serviceType, 
serviceName, timezone)).thenReturn(testAuditMetrics);
 
         RangerAuditMetrics result = 
auditMetricsREST.getLatestAuditMetrics(serviceType, serviceName, timezone);
 
@@ -106,7 +112,7 @@ void testGetLatestAuditMetrics_Success() {
         assertEquals(testAuditMetrics.getId(), result.getId());
         assertEquals(testAuditMetrics.getServiceType(), 
result.getServiceType());
         assertEquals(testAuditMetrics.getNumberOfAudits(), 
result.getNumberOfAudits());
-        verify(solrAccessAuditsService, 
times(1)).getLatestAuditMetrics(serviceType, serviceName, timezone);
+        verify(accessAuditsMetricsService, 
times(1)).getLatestAuditMetrics(serviceType, serviceName, timezone);
     }
 
     @Test
@@ -114,7 +120,7 @@ void testGetLatestAuditMetrics_WebApplicationException() {
         String serviceType = "hive";
         String serviceName = "test-service";
         WebApplicationException webException = new WebApplicationException();
-        when(solrAccessAuditsService.getLatestAuditMetrics(serviceType, 
serviceName, null)).thenThrow(webException);
+        when(accessAuditsMetricsService.getLatestAuditMetrics(serviceType, 
serviceName, null)).thenThrow(webException);
 
         WebApplicationException exception = 
assertThrows(WebApplicationException.class, () ->
                 auditMetricsREST.getLatestAuditMetrics(serviceType, 
serviceName, null));
@@ -127,7 +133,7 @@ void testGetLatestAuditMetrics_WebApplicationException() {
     void testGetLatestAuditMetrics_GeneralException() {
         String serviceType = "hive";
         String serviceName = "test-service";
-        when(solrAccessAuditsService.getLatestAuditMetrics(serviceType, 
serviceName, null))
+        when(accessAuditsMetricsService.getLatestAuditMetrics(serviceType, 
serviceName, null))
                 .thenThrow(new RuntimeException("General exception"));
         when(restErrorUtil.createRESTException(anyString())).thenReturn(new 
WebApplicationException());
 
@@ -141,21 +147,21 @@ void testGetLatestAuditMetrics_GeneralException() {
     void testGetAuditMetrics_Success() {
         Long id = 1L;
         String timezone = "UTC";
-        when(solrAccessAuditsService.getAuditMetrics(id, 
timezone)).thenReturn(testAuditMetrics);
+        when(accessAuditsMetricsService.getAuditMetrics(id, 
timezone)).thenReturn(testAuditMetrics);
 
         RangerAuditMetrics result = auditMetricsREST.getAuditMetrics(id, 
timezone);
 
         assertNotNull(result);
         assertEquals(testAuditMetrics.getId(), result.getId());
         assertEquals(testAuditMetrics.getServiceName(), 
result.getServiceName());
-        verify(solrAccessAuditsService, times(1)).getAuditMetrics(id, 
timezone);
+        verify(accessAuditsMetricsService, times(1)).getAuditMetrics(id, 
timezone);
     }
 
     @Test
     void testGetAuditMetrics_WebApplicationException() {
         Long id = 1L;
         WebApplicationException webException = new WebApplicationException();
-        when(solrAccessAuditsService.getAuditMetrics(id, 
null)).thenThrow(webException);
+        when(accessAuditsMetricsService.getAuditMetrics(id, 
null)).thenThrow(webException);
 
         WebApplicationException exception = 
assertThrows(WebApplicationException.class, () ->
                 auditMetricsREST.getAuditMetrics(id, null));
@@ -167,7 +173,7 @@ void testGetAuditMetrics_WebApplicationException() {
     @Test
     void testGetAuditMetrics_GeneralException() {
         Long id = 1L;
-        when(solrAccessAuditsService.getAuditMetrics(id, null)).thenThrow(new 
RuntimeException("General exception"));
+        when(accessAuditsMetricsService.getAuditMetrics(id, 
null)).thenThrow(new RuntimeException("General exception"));
         when(restErrorUtil.createRESTException(anyString())).thenReturn(new 
WebApplicationException());
 
         assertThrows(WebApplicationException.class, () -> 
auditMetricsREST.getAuditMetrics(id, null));
@@ -180,21 +186,21 @@ void testGetAllLatestRangerAuditMetrics_Success() {
         List<RangerAuditMetrics> metricsList = 
Collections.singletonList(testAuditMetrics);
         String timezone = "Asia/Kolkata";
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter, 
timezone)).thenReturn(metricsList);
+        
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter, 
timezone)).thenReturn(metricsList);
 
         RangerAuditMetricsList result = 
auditMetricsREST.getAllLatestRangerAuditMetrics(httpServletRequest, timezone);
 
         assertNotNull(result);
         assertEquals(1, result.getListSize());
         assertEquals(testAuditMetrics, 
result.getRangerAuditMetricsList().get(0));
-        verify(solrAccessAuditsService, 
times(1)).getLatestAuditMetricsList(testSearchFilter, timezone);
+        verify(accessAuditsMetricsService, 
times(1)).getLatestAuditMetricsList(testSearchFilter, timezone);
     }
 
     @Test
     void testGetAllLatestRangerAuditMetrics_WebApplicationException() {
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
         WebApplicationException webException = new WebApplicationException();
-        
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter, 
null)).thenThrow(webException);
+        
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter, 
null)).thenThrow(webException);
 
         WebApplicationException exception = 
assertThrows(WebApplicationException.class, () ->
                 
auditMetricsREST.getAllLatestRangerAuditMetrics(httpServletRequest, null));
@@ -206,7 +212,7 @@ void 
testGetAllLatestRangerAuditMetrics_WebApplicationException() {
     @Test
     void testGetAllLatestRangerAuditMetrics_EmptyList() {
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter, 
null)).thenReturn(Collections.emptyList());
+        
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter, 
null)).thenReturn(Collections.emptyList());
 
         RangerAuditMetricsList result = 
auditMetricsREST.getAllLatestRangerAuditMetrics(httpServletRequest, null);
 
@@ -217,7 +223,7 @@ void testGetAllLatestRangerAuditMetrics_EmptyList() {
     @Test
     void testGetAllLatestRangerAuditMetrics_GeneralException() {
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        
when(solrAccessAuditsService.getLatestAuditMetricsList(testSearchFilter, null))
+        
when(accessAuditsMetricsService.getLatestAuditMetricsList(testSearchFilter, 
null))
                 .thenThrow(new RuntimeException("General exception"));
         when(restErrorUtil.createRESTException(anyString())).thenReturn(new 
WebApplicationException());
 
@@ -232,20 +238,20 @@ void testGetDailyAuditMetrics_Success() {
         List<RangerAuditMetricsByHours> metricsList = 
Collections.singletonList(testAuditMetricsByHours);
         String timezone = "Asia/Kolkata";
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter, 
timezone)).thenReturn(metricsList);
+        
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter, 
timezone)).thenReturn(metricsList);
 
         RangerAuditMetricsListByHours result = 
auditMetricsREST.getDailyAuditMetrics(httpServletRequest, timezone);
 
         assertNotNull(result);
         assertEquals(1, result.getListSize());
-        verify(solrAccessAuditsService, 
times(1)).getAuditMetricsByHours(testSearchFilter, timezone);
+        verify(accessAuditsMetricsService, 
times(1)).getAuditMetricsByHours(testSearchFilter, timezone);
     }
 
     @Test
     void testGetDailyAuditMetrics_WebApplicationException() {
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
         WebApplicationException webException = new WebApplicationException();
-        when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter, 
null)).thenThrow(webException);
+        
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter, 
null)).thenThrow(webException);
 
         WebApplicationException exception = 
assertThrows(WebApplicationException.class, () ->
                 auditMetricsREST.getDailyAuditMetrics(httpServletRequest, 
null));
@@ -257,7 +263,7 @@ void testGetDailyAuditMetrics_WebApplicationException() {
     @Test
     void testGetDailyAuditMetrics_GeneralException() {
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter, 
null))
+        
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter, null))
                 .thenThrow(new RuntimeException("Daily metrics failed"));
         when(restErrorUtil.createRESTException(anyString())).thenReturn(new 
WebApplicationException());
 
@@ -270,7 +276,7 @@ void testGetDailyAuditMetrics_GeneralException() {
     @Test
     void testGetDailyAuditMetrics_EmptyList() {
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        when(solrAccessAuditsService.getAuditMetricsByHours(testSearchFilter, 
null)).thenReturn(Collections.emptyList());
+        
when(accessAuditsMetricsService.getAuditMetricsByHours(testSearchFilter, 
null)).thenReturn(Collections.emptyList());
 
         RangerAuditMetricsListByHours result = 
auditMetricsREST.getDailyAuditMetrics(httpServletRequest, null);
 
@@ -284,13 +290,13 @@ void testGetDaysAuditMetrics_Success() {
         String timezone = "Asia/Kolkata";
         List<RangerAuditMetricsByDays> metricsList = 
Collections.singletonList(testAuditMetricsByDays);
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, timezone)).thenReturn(metricsList);
+        when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, timezone)).thenReturn(metricsList);
 
         RangerAuditMetricsListByDays result = 
auditMetricsREST.getDaysAuditMetrics(httpServletRequest, olderThanInDays, 
timezone);
 
         assertNotNull(result);
         assertEquals(1, result.getListSize());
-        verify(solrAccessAuditsService, 
times(1)).getAuditMetricsByDays(olderThanInDays, testSearchFilter, timezone);
+        verify(accessAuditsMetricsService, 
times(1)).getAuditMetricsByDays(olderThanInDays, testSearchFilter, timezone);
     }
 
     @Test
@@ -298,7 +304,7 @@ void testGetDaysAuditMetrics_WebApplicationException() {
         Integer olderThanInDays = 7;
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
         WebApplicationException webException = new WebApplicationException();
-        when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, null)).thenThrow(webException);
+        when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, null)).thenThrow(webException);
 
         WebApplicationException exception = 
assertThrows(WebApplicationException.class, () ->
                 auditMetricsREST.getDaysAuditMetrics(httpServletRequest, 
olderThanInDays, null));
@@ -311,7 +317,7 @@ void testGetDaysAuditMetrics_WebApplicationException() {
     void testGetDaysAuditMetrics_GeneralException() {
         Integer olderThanInDays = 7;
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, null))
+        when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, null))
                 .thenThrow(new RuntimeException("Days metrics failed"));
         when(restErrorUtil.createRESTException(anyString())).thenReturn(new 
WebApplicationException());
 
@@ -325,7 +331,7 @@ void testGetDaysAuditMetrics_GeneralException() {
     void testGetDaysAuditMetrics_EmptyList() {
         Integer olderThanInDays = 7;
         when(searchUtil.getSearchFilter(eq(httpServletRequest), 
eq(Collections.emptyList()))).thenReturn(testSearchFilter);
-        when(solrAccessAuditsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, null))
+        when(accessAuditsMetricsService.getAuditMetricsByDays(olderThanInDays, 
testSearchFilter, null))
                 .thenReturn(Collections.emptyList());
 
         RangerAuditMetricsListByDays result = 
auditMetricsREST.getDaysAuditMetrics(httpServletRequest, olderThanInDays, null);
@@ -345,7 +351,7 @@ void testGetDaysAuditMetrics_invalidOlderThanInDays_zero() {
         verify(restErrorUtil, times(1)).createRESTException(
                 contains("olderThanInDays must be between 1 and"),
                 eq(MessageEnums.INVALID_INPUT_DATA));
-        verify(solrAccessAuditsService, 
never()).getAuditMetricsByDays(anyInt(), any(), any());
+        verify(accessAuditsMetricsService, 
never()).getAuditMetricsByDays(anyInt(), any(), any());
     }
 
     @Test
@@ -359,7 +365,7 @@ void 
testGetDaysAuditMetrics_invalidOlderThanInDays_exceedsMax() {
         verify(restErrorUtil, times(1)).createRESTException(
                 contains("olderThanInDays must be between 1 and"),
                 eq(MessageEnums.INVALID_INPUT_DATA));
-        verify(solrAccessAuditsService, 
never()).getAuditMetricsByDays(anyInt(), any(), any());
+        verify(accessAuditsMetricsService, 
never()).getAuditMetricsByDays(anyInt(), any(), any());
     }
 
     private RangerAuditMetrics createTestAuditMetrics() {
diff --git 
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
 
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
index a8f340540..4cd9f6e57 100644
--- 
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
+++ 
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAccessAuditsServiceTest.java
@@ -17,6 +17,7 @@
 package org.apache.ranger.solr;
 
 import org.apache.ranger.AccessAuditsService;
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
 import org.apache.ranger.common.PropertiesUtil;
 import org.apache.ranger.common.RESTErrorUtil;
 import org.apache.ranger.common.SearchCriteria;
@@ -241,7 +242,7 @@ public void getAuditMetrics_success_setsServiceId() throws 
Throwable {
         when(sdDao.getById(1L)).thenReturn(sd);
         when(sd.getName()).thenReturn("hdfs");
         injectField(service, AccessAuditsService.class, "daoManager", 
daoManager);
-        service.auditMetricsHelper.daoManager = daoManager;
+        injectField(service.auditMetricsHelper.auditMetricsHelper, 
AuditMetricsHelper.class, "daoManager", daoManager);
 
         RangerAuditMetrics metrics = service.getAuditMetrics(5L, null);
 
@@ -253,6 +254,7 @@ public void getAuditMetrics_success_setsServiceId() throws 
Throwable {
     private SolrAccessAuditsService createServiceWithHelper() {
         SolrAccessAuditsService service = new SolrAccessAuditsService();
         service.auditMetricsHelper = new SolrAuditMetricsHelper();
+        service.auditMetricsHelper.auditMetricsHelper = new 
AuditMetricsHelper();
         service.auditMetricsHelper.solrMgr = mock(SolrMgr.class);
         service.auditMetricsHelper.solrUtil = mock(SolrUtil.class);
         service.auditMetricsHelper.restErrorUtil = new RESTErrorUtil();
diff --git 
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
 
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
index 8ab339633..870267b6a 100644
--- 
a/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
+++ 
b/security-admin/src/test/java/org/apache/ranger/solr/SolrAuditMetricsHelperTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.ranger.solr;
 
+import org.apache.ranger.audit.metrics.AuditMetricsHelper;
 import org.apache.ranger.common.RESTErrorUtil;
 import org.apache.ranger.db.RangerDaoManager;
 import org.apache.ranger.db.XXServiceDao;
@@ -230,7 +231,19 @@ private SolrAuditMetricsHelper 
createHelper(RangerDaoManager daoManager) {
         helper.solrMgr = mock(SolrMgr.class);
         helper.solrUtil = mock(SolrUtil.class);
         helper.restErrorUtil = new RESTErrorUtil();
-        helper.daoManager = daoManager;
+        helper.auditMetricsHelper = new AuditMetricsHelper();
+
+        if (daoManager != null) {
+            try {
+                java.lang.reflect.Field daoField = 
AuditMetricsHelper.class.getDeclaredField("daoManager");
+
+                daoField.setAccessible(true);
+                daoField.set(helper.auditMetricsHelper, daoManager);
+            } catch (ReflectiveOperationException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
         return helper;
     }
 

Reply via email to