Copilot commented on code in PR #1154:
URL: https://github.com/apache/ranger/pull/1154#discussion_r3776989006
##########
security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java:
##########
@@ -126,6 +153,520 @@ public VXLong getXAccessAuditSearchCount(SearchCriteria
searchCriteria) {
return vXLong;
}
+ public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName) {
+ return getLatestAuditMetrics(serviceType, serviceName, null);
+ }
+
+ public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName, String timezone) {
+ SearchFilter filter = buildSearchFilter(serviceType, serviceName,
null, null, null);
+
+ SolrQuery query = buildMetricsQuery();
+ applyAuditMetricsFilters(query, filter);
+ addLatestMetricsRangeFilter(query);
+ applyTimezone(query, timezone);
+
+ QueryResponse response = runMetricsQuery(query, "latest audit
metrics");
+ long count = response.getResults() != null ?
response.getResults().getNumFound() : 0L;
+ return buildAuditMetrics(serviceType, serviceName, null, null, null,
count);
+ }
+
+ public RangerAuditMetrics getAuditMetrics(Long serviceId) {
+ return getAuditMetrics(serviceId, null);
+ }
+
+ 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 = resolveServiceType(service);
+
+ RangerAuditMetrics metric = getLatestAuditMetrics(serviceType,
serviceName, timezone);
+ metric.setId(serviceId);
+ return metric;
+ }
+
+ public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter
filter) {
+ return getLatestAuditMetricsList(filter, null);
+ }
+
+ public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter
filter, String timezone) {
+ SolrQuery query = buildMetricsQuery();
+ query.set("json.facet", buildAuditMetricsListFacet());
+
+ applyAuditMetricsFilters(query, filter);
+ addLatestMetricsRangeFilter(query);
+ applyTimezone(query, timezone);
+
+ return extractAuditMetricsList(runMetricsQuery(query, "audit metrics
list"), filter);
+ }
+
+ public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int
olderThanInDays, SearchFilter filter) {
+ return getAuditMetricsByDays(olderThanInDays, filter, null);
+ }
+
+ public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int
olderThanInDays, SearchFilter filter, String timezone) {
+ SolrQuery query = buildMetricsQuery();
+ query.set("json.facet", buildAuditAccessMetricsFacet(olderThanInDays));
+
+ applyAuditMetricsFilters(query, filter);
+ applyTimezone(query, timezone);
+
+ return extractAuditMetricsByDays(runMetricsQuery(query, "audit metrics
by days"), filter);
+ }
+
+ public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter
filter) {
+ return getAuditMetricsByHours(filter, null);
+ }
+
+ public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter
filter, String timezone) {
+ SolrQuery query = buildMetricsQuery();
+ query.set("json.facet", buildAuditMetricsByHourFacet());
+
+ applyAuditMetricsFilters(query, filter);
+ addTodayMetricsRangeFilter(query);
+ applyTimezone(query, timezone);
+
+ return extractAuditMetricsByHours(runMetricsQuery(query, "audit
metrics by hours"), filter, timezone);
+ }
+
+ private SolrQuery buildMetricsQuery() {
+ SolrQuery query = new SolrQuery();
+ query.setQuery("*:*");
+ query.setRows(0);
+ return query;
+ }
+
+ private QueryResponse runMetricsQuery(SolrQuery query, String context) {
+ SolrClient solrClient = solrMgr.getSolrClient();
+ if (solrClient == null) {
+ LOGGER.warn("Solr client is null, so not running the query.");
+ throw restErrorUtil.createRESTException("Error connecting to
search engine", MessageEnums.ERROR_SYSTEM);
+ }
+
+ QueryResponse response;
+ try {
+ response = solrUtil.runQuery(solrClient, query);
+ } catch (Throwable e) {
+ LOGGER.error("Error running Solr query for {}.", context, e);
+ throw restErrorUtil.createRESTException("Error running Solr query,
please check solr configs. " + e.getMessage(), MessageEnums.ERROR_SYSTEM);
+ }
+
+ if (response == null || response.getStatus() != 0) {
+ LOGGER.error("Error running Solr query for {}. Query = {},
response = {}", context, query, response);
+ throw restErrorUtil.createRESTException("Unable to connect to
Audit store !!", MessageEnums.ERROR_SYSTEM);
+ }
+
+ return response;
+ }
+
+ 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);
+ }
+
+ private String buildAuditMetricsListFacet() {
+ return "{per_repo:{type:terms,field:repo,limit:-1,sort:\"count desc\","
+ +
"facet:{per_agent:{type:terms,field:agent,limit:-1,missing:true,"
+ +
"facet:{per_cliip:{type:terms,field:cliIP,limit:-1,missing:true,"
+ +
"facet:{per_cluster:{type:terms,field:cluster,limit:-1,missing:true"
+ + "}}}}}}}}";
+ }
+
+ private String buildAuditMetricsByHourFacet() {
+ return
"{per_hour:{type:range,field:evtTime,start:\"NOW/DAY\",end:\"NOW\",gap:\"+1HOUR\"}}";
+ }
+
+ private void addLatestMetricsRangeFilter(SolrQuery query) {
+ if (query == null) {
+ return;
+ }
+
+ query.addFilterQuery("evtTime:[NOW-1DAY TO NOW]");
+ }
+
+ private void addTodayMetricsRangeFilter(SolrQuery query) {
+ if (query == null) {
+ return;
+ }
+
+ 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.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;
+ }
+
+ String serviceName = filter.getParam(SearchFilter.SERVICE_NAME);
+ addFilterQuery(query, "repo", serviceName);
+
+ String serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
+ if (StringUtils.isNotBlank(serviceType)) {
+ long repoType = resolveRepoType(serviceType);
+ if (repoType == MISSING_REPO_TYPE_SENTINEL) {
+ query.addFilterQuery("repoType:-1");
+ } else {
+ query.addFilterQuery("repoType:" + repoType);
+ }
+ }
+
+ addFilterQuery(query, "cluster",
filter.getParam(SearchFilter.CLUSTER_NAME));
+ addFilterQuery(query, "cliIP",
filter.getParam(SearchFilter.CLIENT_IP));
+ addFilterQuery(query, "agent", filter.getParam(SearchFilter.APP_ID));
+ }
+
+ private void addFilterQuery(SolrQuery query, String field, String value) {
+ if (query == null || StringUtils.isBlank(value)) {
+ return;
+ }
+
+ String escapedValue =
ClientUtils.escapeQueryChars(value.trim().toLowerCase());
+ query.addFilterQuery(field + ":" + escapedValue);
+ }
+
+ private void applyTimezone(SolrQuery query, String timezone) {
+ if (query == null || StringUtils.isBlank(timezone)) {
+ return;
+ }
+
+ query.set("TZ", timezone.trim());
+ }
Review Comment:
`applyTimezone()` forwards the raw user-provided timezone to Solr without
validation, but hour-bucket extraction later falls back to UTC for invalid
timezones. Validating here (and falling back to a known-good TZ) avoids
inconsistent behavior and potential query failures when an invalid timezone is
provided.
##########
security-admin/src/main/java/org/apache/ranger/solr/SolrAccessAuditsService.java:
##########
@@ -126,6 +153,520 @@ public VXLong getXAccessAuditSearchCount(SearchCriteria
searchCriteria) {
return vXLong;
}
+ public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName) {
+ return getLatestAuditMetrics(serviceType, serviceName, null);
+ }
+
+ public RangerAuditMetrics getLatestAuditMetrics(String serviceType, String
serviceName, String timezone) {
+ SearchFilter filter = buildSearchFilter(serviceType, serviceName,
null, null, null);
+
+ SolrQuery query = buildMetricsQuery();
+ applyAuditMetricsFilters(query, filter);
+ addLatestMetricsRangeFilter(query);
+ applyTimezone(query, timezone);
+
+ QueryResponse response = runMetricsQuery(query, "latest audit
metrics");
+ long count = response.getResults() != null ?
response.getResults().getNumFound() : 0L;
+ return buildAuditMetrics(serviceType, serviceName, null, null, null,
count);
+ }
+
+ public RangerAuditMetrics getAuditMetrics(Long serviceId) {
+ return getAuditMetrics(serviceId, null);
+ }
+
+ 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 = resolveServiceType(service);
+
+ RangerAuditMetrics metric = getLatestAuditMetrics(serviceType,
serviceName, timezone);
+ metric.setId(serviceId);
+ return metric;
+ }
+
+ public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter
filter) {
+ return getLatestAuditMetricsList(filter, null);
+ }
+
+ public List<RangerAuditMetrics> getLatestAuditMetricsList(SearchFilter
filter, String timezone) {
+ SolrQuery query = buildMetricsQuery();
+ query.set("json.facet", buildAuditMetricsListFacet());
+
+ applyAuditMetricsFilters(query, filter);
+ addLatestMetricsRangeFilter(query);
+ applyTimezone(query, timezone);
+
+ return extractAuditMetricsList(runMetricsQuery(query, "audit metrics
list"), filter);
+ }
+
+ public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int
olderThanInDays, SearchFilter filter) {
+ return getAuditMetricsByDays(olderThanInDays, filter, null);
+ }
+
+ public List<RangerAuditMetricsByDays> getAuditMetricsByDays(int
olderThanInDays, SearchFilter filter, String timezone) {
+ SolrQuery query = buildMetricsQuery();
+ query.set("json.facet", buildAuditAccessMetricsFacet(olderThanInDays));
+
+ applyAuditMetricsFilters(query, filter);
+ applyTimezone(query, timezone);
+
+ return extractAuditMetricsByDays(runMetricsQuery(query, "audit metrics
by days"), filter);
+ }
+
+ public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter
filter) {
+ return getAuditMetricsByHours(filter, null);
+ }
+
+ public List<RangerAuditMetricsByHours> getAuditMetricsByHours(SearchFilter
filter, String timezone) {
+ SolrQuery query = buildMetricsQuery();
+ query.set("json.facet", buildAuditMetricsByHourFacet());
+
+ applyAuditMetricsFilters(query, filter);
+ addTodayMetricsRangeFilter(query);
+ applyTimezone(query, timezone);
+
+ return extractAuditMetricsByHours(runMetricsQuery(query, "audit
metrics by hours"), filter, timezone);
+ }
+
+ private SolrQuery buildMetricsQuery() {
+ SolrQuery query = new SolrQuery();
+ query.setQuery("*:*");
+ query.setRows(0);
+ return query;
+ }
+
+ private QueryResponse runMetricsQuery(SolrQuery query, String context) {
+ SolrClient solrClient = solrMgr.getSolrClient();
+ if (solrClient == null) {
+ LOGGER.warn("Solr client is null, so not running the query.");
+ throw restErrorUtil.createRESTException("Error connecting to
search engine", MessageEnums.ERROR_SYSTEM);
+ }
+
+ QueryResponse response;
+ try {
+ response = solrUtil.runQuery(solrClient, query);
+ } catch (Throwable e) {
+ LOGGER.error("Error running Solr query for {}.", context, e);
+ throw restErrorUtil.createRESTException("Error running Solr query,
please check solr configs. " + e.getMessage(), MessageEnums.ERROR_SYSTEM);
+ }
+
+ if (response == null || response.getStatus() != 0) {
+ LOGGER.error("Error running Solr query for {}. Query = {},
response = {}", context, query, response);
+ throw restErrorUtil.createRESTException("Unable to connect to
Audit store !!", MessageEnums.ERROR_SYSTEM);
+ }
+
+ return response;
+ }
+
+ 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);
+ }
+
+ private String buildAuditMetricsListFacet() {
+ return "{per_repo:{type:terms,field:repo,limit:-1,sort:\"count desc\","
+ +
"facet:{per_agent:{type:terms,field:agent,limit:-1,missing:true,"
+ +
"facet:{per_cliip:{type:terms,field:cliIP,limit:-1,missing:true,"
+ +
"facet:{per_cluster:{type:terms,field:cluster,limit:-1,missing:true"
+ + "}}}}}}}}";
+ }
+
+ private String buildAuditMetricsByHourFacet() {
+ return
"{per_hour:{type:range,field:evtTime,start:\"NOW/DAY\",end:\"NOW\",gap:\"+1HOUR\"}}";
+ }
+
+ private void addLatestMetricsRangeFilter(SolrQuery query) {
+ if (query == null) {
+ return;
+ }
+
+ query.addFilterQuery("evtTime:[NOW-1DAY TO NOW]");
+ }
+
+ private void addTodayMetricsRangeFilter(SolrQuery query) {
+ if (query == null) {
+ return;
+ }
+
+ 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.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;
+ }
+
+ String serviceName = filter.getParam(SearchFilter.SERVICE_NAME);
+ addFilterQuery(query, "repo", serviceName);
+
+ String serviceType = filter.getParam(SearchFilter.SERVICE_TYPE);
+ if (StringUtils.isNotBlank(serviceType)) {
+ long repoType = resolveRepoType(serviceType);
+ if (repoType == MISSING_REPO_TYPE_SENTINEL) {
+ query.addFilterQuery("repoType:-1");
+ } else {
+ query.addFilterQuery("repoType:" + repoType);
+ }
+ }
+
+ addFilterQuery(query, "cluster",
filter.getParam(SearchFilter.CLUSTER_NAME));
+ addFilterQuery(query, "cliIP",
filter.getParam(SearchFilter.CLIENT_IP));
+ addFilterQuery(query, "agent", filter.getParam(SearchFilter.APP_ID));
+ }
+
+ private void addFilterQuery(SolrQuery query, String field, String value) {
+ if (query == null || StringUtils.isBlank(value)) {
+ return;
+ }
+
+ String escapedValue =
ClientUtils.escapeQueryChars(value.trim().toLowerCase());
+ query.addFilterQuery(field + ":" + escapedValue);
+ }
+
+ private void applyTimezone(SolrQuery query, String timezone) {
+ if (query == null || StringUtils.isBlank(timezone)) {
+ return;
+ }
+
+ query.set("TZ", timezone.trim());
+ }
+
+ 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();
+ }
+ }
+
+ repoTypeByServiceType.put(cacheKey, resolved);
+ return resolved;
+ }
+
+ private List<RangerAuditMetrics> extractAuditMetricsList(QueryResponse
response, SearchFilter filter) {
+ NamedList<Object> responseList = response.getResponse();
+ if (responseList == null || !(responseList.get(FACETS_KEY) instanceof
NamedList)) {
+ return Collections.emptyList();
+ }
+
+ NamedList<?> facets = (NamedList<?>) responseList.get(FACETS_KEY);
+ List<?> repoBuckets = extractBuckets(facets.get(FACET_REPO));
+
+ if (repoBuckets == null || repoBuckets.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ String serviceTypeFilter = filter != null ?
filter.getParam(SearchFilter.SERVICE_TYPE) : null;
+ List<RangerAuditMetrics> metrics = new ArrayList<>();
+
+ processRepoBuckets(repoBuckets, metrics, serviceTypeFilter);
+
+ return metrics;
+ }
+
+ private void processRepoBuckets(List<?> repoBuckets,
List<RangerAuditMetrics> metrics, String serviceTypeFilter) {
+ for (Object repoBucket : repoBuckets) {
+ Object repoVal = getBucketValue(repoBucket, BUCKET_VAL);
+ if (repoVal == null) {
+ continue;
+ }
+
+ String serviceName = repoVal.toString();
+ List<?> agentBuckets = extractBuckets(getBucketValue(repoBucket,
FACET_AGENT));
+
+ if (agentBuckets == null || agentBuckets.isEmpty()) {
+ metrics.add(buildAuditMetrics(serviceTypeFilter, serviceName,
null, null, null, bucketCount(repoBucket)));
+ } else {
+ processAgentBuckets(agentBuckets, metrics, serviceTypeFilter,
serviceName);
+ }
+ }
+ }
+
+ private void processAgentBuckets(List<?> agentBuckets,
List<RangerAuditMetrics> metrics, String serviceTypeFilter, String serviceName)
{
+ for (Object agentBucket : agentBuckets) {
+ String appId = bucketValToString(getBucketValue(agentBucket,
BUCKET_VAL));
+ if (appId == null) {
+ continue;
+ }
Review Comment:
The metrics list facet requests `missing:true` for `agent`, but
`processAgentBuckets()` skips buckets where `val` is null. This drops audit
counts for documents that don't have an `agent` field, so `/audit/metrics` can
under-report totals.
##########
agents-common/src/main/java/org/apache/ranger/plugin/model/RangerAuditMetrics.java:
##########
@@ -0,0 +1,143 @@
+/*
+ * 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.plugin.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+@JsonAutoDetect(fieldVisibility = Visibility.ANY)
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
Review Comment:
These model classes use the deprecated `@JsonSerialize(include=...)`
pattern, while the codebase largely standardizes on `@JsonInclude(...)` (e.g.,
`agents-common/.../RangerBaseModelObject.java:37-39`). Using
`@JsonInclude(Include.NON_NULL)` avoids deprecated annotations and aligns with
existing conventions.
##########
agents-common/src/main/java/org/apache/ranger/plugin/model/RangerAuditMetricsByHours.java:
##########
@@ -0,0 +1,145 @@
+/*
+ * 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.plugin.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+@JsonAutoDetect(fieldVisibility = Visibility.ANY)
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
Review Comment:
These model classes use the deprecated `@JsonSerialize(include=...)`
pattern, while the codebase largely standardizes on `@JsonInclude(...)` (e.g.,
`agents-common/.../RangerBaseModelObject.java:37-39`). Using
`@JsonInclude(Include.NON_NULL)` avoids deprecated annotations and aligns with
existing conventions.
##########
security-admin/src/main/java/org/apache/ranger/view/RangerAuditMetricsListByDays.java:
##########
@@ -0,0 +1,65 @@
+/*
+ * 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.view;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.ranger.common.view.VList;
+import org.apache.ranger.plugin.model.RangerAuditMetricsByDays;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility =
Visibility.NONE, fieldVisibility = Visibility.ANY)
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class RangerAuditMetricsListByDays extends VList {
+ private static final long serialVersionUID = 1L;
+
+ List<RangerAuditMetricsByDays> auditMetricsByDays = new ArrayList<>();
+
+ public RangerAuditMetricsListByDays() {
+ super();
+ }
+
+ public RangerAuditMetricsListByDays(List<RangerAuditMetricsByDays>
objList) {
+ super(objList);
+ this.auditMetricsByDays = objList;
+ }
+
+ public List<RangerAuditMetricsByDays> getAuditMetricsListByUnit() {
+ return auditMetricsByDays;
+ }
Review Comment:
The getter name `getAuditMetricsListByUnit()` doesn’t match the class
purpose or the corresponding setter `setAuditMetricsListByDays()`. This makes
the API confusing for callers and inconsistent with
`RangerAuditMetricsListByHours`.
##########
agents-common/src/main/java/org/apache/ranger/plugin/model/RangerAuditMetricsByDays.java:
##########
@@ -0,0 +1,148 @@
+/*
+ * 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.plugin.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+@JsonAutoDetect(getterVisibility = Visibility.NONE, setterVisibility =
Visibility.NONE, fieldVisibility = Visibility.ANY)
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
Review Comment:
These model classes use the deprecated `@JsonSerialize(include=...)`
pattern, while the codebase largely standardizes on `@JsonInclude(...)` (e.g.,
`agents-common/.../RangerBaseModelObject.java:37-39`). Using
`@JsonInclude(Include.NON_NULL)` avoids deprecated annotations and aligns with
existing conventions.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]