Commit 4a938d87 by apoorvnaik

ATLAS-2578: Update metric queries for faster execution

Change-Id: Ic17ce74f8309fa61f9946d7295b1d161374ebe26
parent 85aef3c0
...@@ -36,13 +36,13 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ ...@@ -36,13 +36,13 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown=true) @JsonIgnoreProperties(ignoreUnknown=true)
public class AtlasMetrics { public class AtlasMetrics {
private Map<String, Map<String, Number>> data; private Map<String, Map<String, Object>> data;
public AtlasMetrics() { public AtlasMetrics() {
setData(null); setData(null);
} }
public AtlasMetrics(Map<String, Map<String, Number>> data) { public AtlasMetrics(Map<String, Map<String, Object>> data) {
setData(data); setData(data);
} }
...@@ -52,41 +52,41 @@ public class AtlasMetrics { ...@@ -52,41 +52,41 @@ public class AtlasMetrics {
} }
} }
public Map<String, Map<String, Number>> getData() { public Map<String, Map<String, Object>> getData() {
return data; return data;
} }
public void setData(Map<String, Map<String, Number>> data) { public void setData(Map<String, Map<String, Object>> data) {
this.data = data; this.data = data;
} }
@JsonIgnore @JsonIgnore
public void addData(String groupKey, String key, Number value) { public void addMetric(String groupKey, String key, Object value) {
Map<String, Map<String, Number>> data = this.data; Map<String, Map<String, Object>> data = this.data;
if (data == null) { if (data == null) {
data = new HashMap<>(); data = new HashMap<>();
} }
Map<String, Number> metricMap = data.get(groupKey); Map<String, Object> metricMap = data.computeIfAbsent(groupKey, k -> new HashMap<>());
if (metricMap == null) {
metricMap = new HashMap<>();
data.put(groupKey, metricMap);
}
metricMap.put(key, value); metricMap.put(key, value);
setData(data); setData(data);
} }
@JsonIgnore @JsonIgnore
public Number getMetric(String groupKey, String key) { public Number getNumericMetric(String groupKey, String key) {
Map<String, Map<String, Number>> data = this.data; Object metric = getMetric(groupKey, key);
if (data == null) { return metric instanceof Number ? (Number) metric : null;
return null; }
} else {
Map<String, Number> metricMap = data.get(groupKey); @JsonIgnore
if (metricMap == null || metricMap.isEmpty()) { public Object getMetric(String groupKey, String key) {
return null; Map<String, Map<String, Object>> data = this.data;
} else { Object ret = null;
return metricMap.get(key); if (data != null) {
Map<String, Object> metricMap = data.get(groupKey);
if (metricMap != null && !metricMap.isEmpty()) {
ret = metricMap.get(key);
} }
} }
return ret;
} }
} }
...@@ -21,22 +21,11 @@ public class AtlasGremlin2QueryProvider extends AtlasGremlinQueryProvider { ...@@ -21,22 +21,11 @@ public class AtlasGremlin2QueryProvider extends AtlasGremlinQueryProvider {
@Override @Override
public String getQuery(final AtlasGremlinQuery gremlinQuery) { public String getQuery(final AtlasGremlinQuery gremlinQuery) {
switch (gremlinQuery) { switch (gremlinQuery) {
case TYPE_COUNT_METRIC: case ENTITY_ACTIVE_METRIC:
return "g.V().has('__type', 'typeSystem').filter({!it.'__type.category'.name().matches('TRAIT')}).count()"; return "g.V().has('__typeName', T.in, [%s]).has('__state', 'ACTIVE').groupCount{it.getProperty('__typeName')}.cap.toList()";
case TYPE_UNUSED_COUNT_METRIC:
return "g.V('__type', 'typeSystem').filter({ !it.getProperty('__type.category').name().matches('TRAIT') && it.inE().count() == 0}).count()";
case ENTITY_COUNT_METRIC:
return "g.V().has('__superTypeNames', T.in, ['Referenceable']).count()";
case TAG_COUNT_METRIC:
return "g.V().has('__type', 'typeSystem').filter({it.getProperty('__type.category').name().matches('TRAIT')}).count()";
case ENTITY_DELETED_METRIC: case ENTITY_DELETED_METRIC:
return "g.V().has('__typeName', T.in, g.V().has('__type', 'typeSystem').filter{it.getProperty('__type.category').name().matches('CLASS')}.'__type.name'.toSet()).has('__status', 'DELETED').count()"; return "g.V().has('__typeName', T.in, [%s]).has('__state', 'DELETED').groupCount{it.getProperty('__typeName')}.cap.toList()";
case ENTITIES_PER_TYPE_METRIC:
return "g.V().has('__typeName', T.in, g.V().has('__type', 'typeSystem').filter{it.getProperty('__type.category').name() == 'CLASS'}.'__type.name'.toSet()).groupCount{it.getProperty('__typeName')}.cap.toList()";
case TAGGED_ENTITIES_METRIC:
return "g.V().has('__traitNames', T.in, g.V().has('__type', 'typeSystem').filter{it.getProperty('__type.category').name() == 'TRAIT'}.'__type.name'.toSet()).count()";
case ENTITIES_FOR_TAG_METRIC:
return "g.V().has('__typeName', T.in, g.V().has('__type', 'typeSystem').filter{it.getProperty('__type.category').name() == 'TRAIT'}.'__type.name'.toSet()).groupCount{it.getProperty('__typeName')}.cap.toList()";
case EXPORT_BY_GUID_FULL: case EXPORT_BY_GUID_FULL:
return "g.V('__guid', startGuid).bothE().bothV().has('__guid').transform{[__guid:it.__guid,isProcess:(it.__superTypeNames != null) ? it.__superTypeNames.contains('Process') : false ]}.dedup().toList()"; return "g.V('__guid', startGuid).bothE().bothV().has('__guid').transform{[__guid:it.__guid,isProcess:(it.__superTypeNames != null) ? it.__superTypeNames.contains('Process') : false ]}.dedup().toList()";
case EXPORT_BY_GUID_CONNECTED_IN_EDGE: case EXPORT_BY_GUID_CONNECTED_IN_EDGE:
......
...@@ -23,10 +23,10 @@ public class AtlasGremlin3QueryProvider extends AtlasGremlin2QueryProvider { ...@@ -23,10 +23,10 @@ public class AtlasGremlin3QueryProvider extends AtlasGremlin2QueryProvider {
// In case any overrides are necessary, a specific switch case can be added here to // In case any overrides are necessary, a specific switch case can be added here to
// return Gremlin 3 specific query otherwise delegate to super.getQuery // return Gremlin 3 specific query otherwise delegate to super.getQuery
switch (gremlinQuery) { switch (gremlinQuery) {
case TYPE_UNUSED_COUNT_METRIC: case ENTITY_ACTIVE_METRIC:
return "g.V().has('__type', 'typeSystem').filter({ !it.getProperty('__type.category').name().matches('TRAIT') && it.inE().count() == 0}).count()"; return "g.V().has('__typeName', within(%s)).has('__state', 'ACTIVE').groupCount().by('__typeName').toList()";
case ENTITY_COUNT_METRIC: case ENTITY_DELETED_METRIC:
return "g.V().has('__superTypeNames', within(['Referenceable'])).count()"; return "g.V().has('__typeName', within(%s)).has('__state', 'DELETED').groupCount().by('__typeName').toList()";
case EXPORT_TYPE_STARTS_WITH: case EXPORT_TYPE_STARTS_WITH:
return "g.V().has('__typeName',typeName).filter({it.get().value(attrName).startsWith(attrValue)}).has('__guid').values('__guid').toList()"; return "g.V().has('__typeName',typeName).filter({it.get().value(attrName).startsWith(attrValue)}).has('__guid').values('__guid').toList()";
case EXPORT_TYPE_ENDS_WITH: case EXPORT_TYPE_ENDS_WITH:
......
...@@ -34,8 +34,8 @@ public abstract class AtlasGremlinQueryProvider { ...@@ -34,8 +34,8 @@ public abstract class AtlasGremlinQueryProvider {
// Metrics related Queries // Metrics related Queries
TYPE_COUNT_METRIC, TYPE_COUNT_METRIC,
TYPE_UNUSED_COUNT_METRIC, TYPE_UNUSED_COUNT_METRIC,
ENTITY_COUNT_METRIC,
TAG_COUNT_METRIC, TAG_COUNT_METRIC,
ENTITY_ACTIVE_METRIC,
ENTITY_DELETED_METRIC, ENTITY_DELETED_METRIC,
ENTITIES_PER_TYPE_METRIC, ENTITIES_PER_TYPE_METRIC,
TAGGED_ENTITIES_METRIC, TAGGED_ENTITIES_METRIC,
......
...@@ -17,19 +17,16 @@ ...@@ -17,19 +17,16 @@
*/ */
package org.apache.atlas.services; package org.apache.atlas.services;
import org.apache.atlas.TestModules;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.metrics.AtlasMetrics; import org.apache.atlas.model.metrics.AtlasMetrics;
import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.runner.LocalSolrRunner;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.util.AtlasGremlin3QueryProvider;
import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.Configuration;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.SkipException; import org.testng.SkipException;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -45,34 +42,40 @@ import static org.mockito.Mockito.*; ...@@ -45,34 +42,40 @@ import static org.mockito.Mockito.*;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
@Guice(modules = TestModules.TestOnlyModule.class)
public class MetricsServiceTest { public class MetricsServiceTest {
private Configuration mockConfig = mock(Configuration.class); private Configuration mockConfig = mock(Configuration.class);
private AtlasTypeRegistry mockTypeRegistry = mock(AtlasTypeRegistry.class); private AtlasTypeRegistry mockTypeRegistry = mock(AtlasTypeRegistry.class);
private AtlasGraph mockGraph = mock(AtlasGraph.class); private AtlasGraph mockGraph = mock(AtlasGraph.class);
private MetricsService metricsService; private MetricsService metricsService;
private List<Map> mockMapList = new ArrayList<>(); private List<Map> activeEntityCountList = new ArrayList<>();
private Number mockCount = 10; private List<Map> deletedEntityCountList = new ArrayList<>();
@BeforeClass @BeforeClass
public void init() throws Exception { public void init() throws Exception {
try { try {
Map<String, Object> mockMap = new HashMap<>(); Map<String, Object> activeEntityCount = new HashMap<>();
mockMap.put("a", 1); activeEntityCount.put("a", 1);
mockMap.put("b", 2); activeEntityCount.put("b", 2);
mockMap.put("c", 3); activeEntityCount.put("d", 5);
mockMapList.add(mockMap); activeEntityCount.put("e", 10);
activeEntityCount.put("f", 15);
activeEntityCountList.add(activeEntityCount);
Map<String, Object> deletedEntityCount = new HashMap<>();
deletedEntityCount.put("b", 5);
deletedEntityCountList.add(deletedEntityCount);
when(mockConfig.getInt(anyString(), anyInt())).thenReturn(5); when(mockConfig.getInt(anyString(), anyInt())).thenReturn(5);
assertEquals(mockConfig.getInt("test", 1), 5); assertEquals(mockConfig.getInt("test", 1), 5);
when(mockConfig.getString(anyString(), anyString())) when(mockConfig.getString(anyString(), anyString())).thenReturn("toList()", "toList()");
.thenReturn("count()", "count()", "count()", "count()", "count()", "toList()", "count()", "toList()"); when(mockTypeRegistry.getAllTypeNames()).thenReturn(Arrays.asList("a", "b", "c", "d", "e", "f"));
when(mockTypeRegistry.getAllEntityDefNames()).thenReturn(Arrays.asList("a", "b", "c"));
when(mockTypeRegistry.getAllEntityDefNames()).thenReturn(Arrays.asList("a", "b", "c")); when(mockTypeRegistry.getAllEntityDefNames()).thenReturn(Arrays.asList("a", "b", "c"));
when(mockTypeRegistry.getAllClassificationDefNames()).thenReturn(Arrays.asList("d", "e", "f"));
// when(mockTypeRegistry.getAllEntityDefNames()).thenReturn(Arrays.asList("a", "b", "c"));
setupMockGraph(); setupMockGraph();
metricsService = new MetricsService(mockConfig, mockGraph); metricsService = new MetricsService(mockConfig, mockGraph, mockTypeRegistry, new AtlasGremlin3QueryProvider());
} }
catch(Exception e) { catch(Exception e) {
throw new SkipException("MetricsServicesTest: init failed!", e); throw new SkipException("MetricsServicesTest: init failed!", e);
...@@ -88,16 +91,9 @@ public class MetricsServiceTest { ...@@ -88,16 +91,9 @@ public class MetricsServiceTest {
private void setupMockGraph() throws AtlasBaseException { private void setupMockGraph() throws AtlasBaseException {
if (mockGraph == null) mockGraph = mock(AtlasGraph.class); if (mockGraph == null) mockGraph = mock(AtlasGraph.class);
when(mockGraph.executeGremlinScript(anyString(), eq(false))).thenAnswer(new Answer<Object>() { when(mockGraph.executeGremlinScript(anyString(), eq(false)))
@Override .thenReturn(activeEntityCountList)
public Object answer(InvocationOnMock invocationOnMock) throws Throwable { .thenReturn(deletedEntityCountList);
if (((String)invocationOnMock.getArguments()[0]).contains("count()")) {
return mockCount;
} else {
return mockMapList;
}
}
});
} }
@Test @Test
...@@ -105,29 +101,28 @@ public class MetricsServiceTest { ...@@ -105,29 +101,28 @@ public class MetricsServiceTest {
assertNotNull(metricsService); assertNotNull(metricsService);
AtlasMetrics metrics = metricsService.getMetrics(false); AtlasMetrics metrics = metricsService.getMetrics(false);
assertNotNull(metrics); assertNotNull(metrics);
Number aCount = metrics.getMetric("entity", "a"); Map activeMetrics = (Map) metrics.getMetric("entity", "entityActive");
assertNotNull(aCount); assertNotNull(activeMetrics);
assertEquals(aCount, 1); assertEquals(activeMetrics.get("a"), 1);
assertEquals(activeMetrics.get("b"), 2);
Number bCount = metrics.getMetric("entity", "b"); Map deletedMetrics = (Map) metrics.getMetric("entity", "entityDeleted");
assertNotNull(bCount); assertEquals(deletedMetrics.get("b"), 5);
assertEquals(bCount, 2);
Number cCount = metrics.getMetric("entity", "c"); Number unusedTypeCount = metrics.getNumericMetric("general", "typeUnusedCount");
assertNotNull(cCount); assertEquals(unusedTypeCount, 1);
assertEquals(cCount, 3);
Number aTags = metrics.getMetric("tag", "a"); Number cCount = metrics.getNumericMetric("general", "entityCount");
assertNotNull(aTags); assertEquals(cCount, 8);
assertEquals(aTags, 1);
Number bTags = metrics.getMetric("tag", "b"); Number aTags = (Number) metrics.getMetric("general", "tagCount");
assertNotNull(bTags); assertEquals(aTags, 3);
assertEquals(bTags, 2);
Number cTags = metrics.getMetric("tag", "c"); Map taggedEntityMetric = (Map) metrics.getMetric("tag", "tagEntities");
assertNotNull(cTags); assertNotNull(taggedEntityMetric);
assertEquals(cTags, 3); assertEquals(taggedEntityMetric.get("d"), 5);
assertEquals(taggedEntityMetric.get("e"), 10);
assertEquals(taggedEntityMetric.get("f"), 15);
verify(mockGraph, atLeastOnce()).executeGremlinScript(anyString(), anyBoolean()); verify(mockGraph, atLeastOnce()).executeGremlinScript(anyString(), anyBoolean());
......
...@@ -99,9 +99,9 @@ public class AdminResource { ...@@ -99,9 +99,9 @@ public class AdminResource {
private Response version; private Response version;
private static Configuration atlasProperties;
private final ServiceState serviceState; private final ServiceState serviceState;
private final MetricsService metricsService; private final MetricsService metricsService;
private static Configuration atlasProperties;
private final ExportService exportService; private final ExportService exportService;
private final ImportService importService; private final ImportService importService;
private final SearchTracker activeSearches; private final SearchTracker activeSearches;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment