diff --git a/common/src/main/java/org/apache/atlas/service/metrics/MetricUtils.java b/common/src/main/java/org/apache/atlas/service/metrics/MetricUtils.java index 60008e5f9d..c309190391 100644 --- a/common/src/main/java/org/apache/atlas/service/metrics/MetricUtils.java +++ b/common/src/main/java/org/apache/atlas/service/metrics/MetricUtils.java @@ -6,6 +6,7 @@ import io.micrometer.prometheus.PrometheusConfig; import io.micrometer.prometheus.PrometheusMeterRegistry; import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,18 +37,15 @@ public class MetricUtils { private static final PrometheusMeterRegistry METER_REGISTRY; static { - METER_REGISTRY = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); - METER_REGISTRY.config().withHighCardinalityTagsDetector().commonTags(SERVICE, ATLAS_METASTORE, INTEGRATION, LOCAL); - Metrics.globalRegistry.add(METER_REGISTRY); - } - - public MetricUtils() { try { METRIC_URI_PATTERNS_MAP = Arrays.stream(ApplicationProperties.get().getStringArray(ATLAS_METRICS_URI_PATTERNS)) .distinct().collect(Collectors.toMap(uri->uri, uri->uri.replaceAll(REGEX_URI_PLACEHOLDER, "*"))); } catch (Exception e) { LOG.error("Failed to load 'atlas.metrics.uri_patterns from properties"); } + METER_REGISTRY = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + METER_REGISTRY.config().withHighCardinalityTagsDetector().commonTags(SERVICE, ATLAS_METASTORE, INTEGRATION, LOCAL); + Metrics.globalRegistry.add(METER_REGISTRY); } public Timer.Sample start(String uri) { @@ -78,7 +76,7 @@ private Tags getTags(String httpMethod, int httpResponseStatus, String uri) { URI, matchCanonicalPattern(uri).get()); } - private Optional matchCanonicalPattern(String uri) { + public static Optional matchCanonicalPattern(String uri) { if (Objects.isNull(uri) || uri.isEmpty()) { return Optional.empty(); } diff --git a/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistry.java b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistry.java index 19dd1d69fe..1730fb50de 100644 --- a/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistry.java +++ b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistry.java @@ -7,7 +7,7 @@ public interface MetricsRegistry { - void collect(String requestId, AtlasPerfMetrics metrics); + void collect(String requestId, String requestUri, AtlasPerfMetrics metrics); void scrape(PrintWriter writer) throws IOException; diff --git a/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistryServiceImpl.java b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistryServiceImpl.java index 34493e0d51..65a5be31f9 100644 --- a/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistryServiceImpl.java +++ b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistryServiceImpl.java @@ -28,6 +28,7 @@ public class MetricsRegistryServiceImpl implements MetricsRegistry { private static final Logger LOG = LoggerFactory.getLogger(MetricsRegistryServiceImpl.class); private static final String NAME = "name"; + private static final String URI = "uri"; private static final String METHOD_DIST_SUMMARY = "method_dist_summary"; private static final double[] PERCENTILES = {0.99}; private static final String METHOD_LEVEL_METRICS_ENABLE = "atlas.metrics.method_level.enable"; @@ -40,7 +41,7 @@ public MetricsRegistryServiceImpl() throws AtlasException { } @Override - public void collect(String requestId, AtlasPerfMetrics metrics) { + public void collect(String requestId, String requestUri, AtlasPerfMetrics metrics) { try { if (!ApplicationProperties.get().getBoolean(METHOD_LEVEL_METRICS_ENABLE, false)) { return; @@ -49,7 +50,7 @@ public void collect(String requestId, AtlasPerfMetrics metrics) { for (String name : this.filteredMethods) { if(metrics.hasMetric(name)) { AtlasPerfMetrics.Metric metric = metrics.getMetric(name); - Timer.builder(METHOD_DIST_SUMMARY).tags(Tags.of(NAME, metric.getName())).publishPercentiles(PERCENTILES) + Timer.builder(METHOD_DIST_SUMMARY).tags(Tags.of(NAME, metric.getName(), URI, requestUri)).publishPercentiles(PERCENTILES) .register(getMeterRegistry()).record(metric.getTotalTimeMSecs(), TimeUnit.MILLISECONDS); } } diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java index 05a7b72b16..11120c466b 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java +++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java @@ -269,7 +269,8 @@ public enum AtlasErrorCode { FAILED_TO_REFRESH_TYPE_DEF_CACHE(500, "ATLAS-500-00-20", "Failed to refresh type-def cache"), CINV_UNHEALTHY(500, "ATLAS-500-00-21", "Unable to process type-definition operations"), RUNTIME_EXCEPTION(500, "ATLAS-500-00-020", "Runtime exception {0}"), - KEYCLOAK_INIT_FAILED(500, "ATLAS-500-00-021", "Failed to initialize keycloak client: {0}"), + KEYCLOAK_INIT_FAILED(500, "ATLAS-500-00-022", "Failed to initialize keycloak client: {0}"), + BATCH_SIZE_TOO_LARGE(406, "ATLAS-406-00-001", "Batch size is too large, please use a smaller batch size"), CLASSIFICATION_CURRENTLY_BEING_PROPAGATED(400, "ATLAS-400-00-105", "Classification {0} is currently being propagated."), diff --git a/repository/src/main/java/org/apache/atlas/GraphTransactionInterceptor.java b/repository/src/main/java/org/apache/atlas/GraphTransactionInterceptor.java index 5ce23cf5a4..2d072d95fc 100644 --- a/repository/src/main/java/org/apache/atlas/GraphTransactionInterceptor.java +++ b/repository/src/main/java/org/apache/atlas/GraphTransactionInterceptor.java @@ -128,7 +128,11 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } else { doRollback(logRollback, t); } - throw t; + if (checkForBatchTooLargeError(t)) { + throw new AtlasBaseException(AtlasErrorCode.BATCH_SIZE_TOO_LARGE, t); + } else { + throw t; + } } } finally { RequestContext.get().endMetricRecord(metric); @@ -167,6 +171,22 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } } + public boolean checkForBatchTooLargeError(Throwable t) { + Throwable currentCause = t; + while (currentCause != null) { + String message = currentCause.getMessage(); + if (message != null && + message.contains("Batch too large") && + currentCause.getClass().getSimpleName().equals("InvalidQueryException")) { + return true; + } + currentCause = currentCause.getCause(); + } + return false; + } + + + private void doCommitOrRollback(final String invokingClass, final String invokedMethodName) { if (innerFailure.get()) { if (LOG.isDebugEnabled()) { diff --git a/server-api/src/main/java/org/apache/atlas/RequestContext.java b/server-api/src/main/java/org/apache/atlas/RequestContext.java index 99568e89ee..750d020406 100644 --- a/server-api/src/main/java/org/apache/atlas/RequestContext.java +++ b/server-api/src/main/java/org/apache/atlas/RequestContext.java @@ -95,7 +95,7 @@ public class RequestContext { private MetricsRegistry metricsRegistry; private boolean skipAuthorizationCheck = false; private Set deletedEdgesIdsForResetHasLineage = new HashSet<>(0); - + private String requestUri; private RequestContext() { } @@ -159,7 +159,7 @@ public void clearCache() { if (metrics != null && !metrics.isEmpty()) { METRICS.debug(metrics.toString()); if (Objects.nonNull(this.metricsRegistry)){ - this.metricsRegistry.collect(traceId, metrics); + this.metricsRegistry.collect(traceId, this.requestUri, metrics); } metrics.clear(); } @@ -642,6 +642,14 @@ public void setMetricRegistry(MetricsRegistry metricsRegistry) { this.metricsRegistry = metricsRegistry; } + public void setUri(String uri) { + this.requestUri = uri; + } + + public String getRequestUri() { + return this.requestUri; + } + public class EntityGuidPair { private final Object entity; private final String guid; diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java index 30b3a48edd..d3cb21b94d 100755 --- a/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java @@ -20,6 +20,7 @@ import org.apache.atlas.*; import org.apache.atlas.authorize.AtlasAuthorizationUtils; +import org.apache.atlas.service.metrics.MetricUtils; import org.apache.atlas.service.metrics.MetricsRegistry; import org.apache.atlas.util.AtlasRepositoryConfiguration; import org.apache.atlas.web.util.DateTimeHelper; @@ -95,6 +96,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha RequestContext.clear(); RequestContext requestContext = RequestContext.get(); + requestContext.setUri(MetricUtils.matchCanonicalPattern(httpRequest.getRequestURI()).orElse(EMPTY)); requestContext.setTraceId(internalRequestId); requestContext.setUser(user, userGroups); requestContext.setClientIPAddress(AtlasAuthorizationUtils.getRequestIpAddress(httpRequest));