blob: ceb2528229c663fb133bd3fff6b7675f5ab6a39d [file] [log] [blame]
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.atlas.services;
import org.apache.atlas.annotation.AtlasService;
import org.apache.atlas.annotation.GraphTransaction;
import org.apache.atlas.authorize.AtlasAuthorizationUtils;
import org.apache.atlas.authorize.AtlasTypesDefFilterRequest;
import org.apache.atlas.model.instance.AtlasEntity.Status;
import org.apache.atlas.model.metrics.AtlasMetrics;
import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.util.AtlasMetricJVMUtil;
import org.apache.atlas.util.AtlasMetricsUtil;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static org.apache.atlas.discovery.SearchProcessor.AND_STR;
import static org.apache.atlas.model.instance.AtlasEntity.Status.ACTIVE;
import static org.apache.atlas.model.instance.AtlasEntity.Status.DELETED;
import static org.apache.atlas.repository.Constants.*;
@AtlasService
public class MetricsService {
private static final Logger LOG = LoggerFactory.getLogger(MetricsService.class);
// Query Category constants
public static final String TYPE = "type";
public static final String TYPE_SUBTYPES = "typeAndSubTypes";
public static final String ENTITY = "entity";
public static final String TAG = "tag";
public static final String GENERAL = "general";
public static final String SYSTEM = "system";
// Query names
protected static final String METRIC_COLLECTION_TIME = "collectionTime";
protected static final String METRIC_STATS = "stats";
protected static final String METRIC_TYPE_COUNT = TYPE + "Count";
protected static final String METRIC_TYPE_UNUSED_COUNT = TYPE + "UnusedCount";
protected static final String METRIC_ENTITY_COUNT = ENTITY + "Count";
protected static final String METRIC_ENTITY_DELETED = ENTITY + "Deleted";
protected static final String METRIC_ENTITY_ACTIVE = ENTITY + "Active";
protected static final String METRIC_ENTITY_SHELL = ENTITY + "Shell";
protected static final String METRIC_TAG_COUNT = TAG + "Count";
protected static final String METRIC_ENTITIES_PER_TAG = TAG + "Entities";
protected static final String METRIC_RUNTIME = "runtime";
protected static final String METRIC_MEMORY = "memory";
protected static final String METRIC_OS = "os";
protected static final String METRIC_ENTITY_ACTIVE_INCL_SUBTYPES = ENTITY + "Active"+"-"+TYPE_SUBTYPES;
protected static final String METRIC_ENTITY_DELETED_INCL_SUBTYPES = ENTITY + "Deleted"+"-"+TYPE_SUBTYPES;
protected static final String METRIC_ENTITY_SHELL_INCL_SUBTYPES = ENTITY + "Shell"+"-"+TYPE_SUBTYPES;
private final AtlasGraph atlasGraph;
private final AtlasTypeRegistry typeRegistry;
private final AtlasMetricsUtil metricsUtil;
private final String indexSearchPrefix = AtlasGraphUtilsV2.getIndexSearchPrefix();
@Inject
public MetricsService(final AtlasGraph graph, final AtlasTypeRegistry typeRegistry, AtlasMetricsUtil metricsUtil) {
this.atlasGraph = graph;
this.typeRegistry = typeRegistry;
this.metricsUtil = metricsUtil;
}
@SuppressWarnings("unchecked")
@GraphTransaction
public AtlasMetrics getMetrics() {
final AtlasTypesDef typesDef = getTypesDef();
Collection<AtlasEntityDef> entityDefs = typesDef.getEntityDefs();
Collection<AtlasClassificationDef> classificationDefs = typesDef.getClassificationDefs();
Map<String, Long> activeEntityCount = new HashMap<>();
Map<String, Long> deletedEntityCount = new HashMap<>();
Map<String, Long> shellEntityCount = new HashMap<>();
Map<String, Long> taggedEntityCount = new HashMap<>();
Map<String, Long> activeEntityCountTypeAndSubTypes = new HashMap<>();
Map<String, Long> deletedEntityCountTypeAndSubTypes = new HashMap<>();
Map<String, Long> shellEntityCountTypeAndSubTypes = new HashMap<>();
long unusedTypeCount = 0;
long totalEntities = 0;
if (entityDefs != null) {
for (AtlasEntityDef entityDef : entityDefs) {
long activeCount = getTypeCount(entityDef.getName(), ACTIVE);
long deletedCount = getTypeCount(entityDef.getName(), DELETED);
long shellCount = getTypeShellCount(entityDef.getName());
if (activeCount > 0) {
activeEntityCount.put(entityDef.getName(), activeCount);
totalEntities += activeCount;
}
if (deletedCount > 0) {
deletedEntityCount.put(entityDef.getName(), deletedCount);
totalEntities += deletedCount;
}
if (activeCount == 0 && deletedCount == 0) {
unusedTypeCount++;
}
if (shellCount > 0) {
shellEntityCount.put(entityDef.getName(), shellCount);
}
}
for (AtlasEntityDef entityDef : entityDefs) {
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entityDef.getName());
long entityActiveCount = 0;
long entityDeletedCount = 0;
long entityShellCount = 0;
for (String type : entityType.getTypeAndAllSubTypes()) {
entityActiveCount += activeEntityCount.get(type) == null ? 0 : activeEntityCount.get(type);
entityDeletedCount += deletedEntityCount.get(type) == null ? 0 : deletedEntityCount.get(type);
entityShellCount += shellEntityCount.get(type) == null ? 0 : shellEntityCount.get(type);
}
if (entityActiveCount > 0) {
activeEntityCountTypeAndSubTypes.put(entityType.getTypeName(), entityActiveCount);
}
if (entityDeletedCount > 0) {
deletedEntityCountTypeAndSubTypes.put(entityType.getTypeName(), entityDeletedCount);
}
if (entityShellCount > 0) {
shellEntityCountTypeAndSubTypes.put(entityType.getTypeName(), entityShellCount);
}
}
}
if (classificationDefs != null) {
for (AtlasClassificationDef classificationDef : classificationDefs) {
long count = getTypeCount(classificationDef.getName(), ACTIVE);
if (count > 0) {
taggedEntityCount.put(classificationDef.getName(), count);
}
}
}
AtlasMetrics metrics = new AtlasMetrics();
metrics.addMetric(GENERAL, METRIC_COLLECTION_TIME, System.currentTimeMillis());
metrics.addMetric(GENERAL, METRIC_STATS, metricsUtil.getStats()); //add atlas server stats
metrics.addMetric(GENERAL, METRIC_TYPE_COUNT, getAllTypesCount());
metrics.addMetric(GENERAL, METRIC_TAG_COUNT, getAllTagsCount());
metrics.addMetric(GENERAL, METRIC_TYPE_UNUSED_COUNT, unusedTypeCount);
metrics.addMetric(GENERAL, METRIC_ENTITY_COUNT, totalEntities);
metrics.addMetric(ENTITY, METRIC_ENTITY_ACTIVE, activeEntityCount);
metrics.addMetric(ENTITY, METRIC_ENTITY_DELETED, deletedEntityCount);
metrics.addMetric(ENTITY, METRIC_ENTITY_SHELL, shellEntityCount);
metrics.addMetric(ENTITY, METRIC_ENTITY_ACTIVE_INCL_SUBTYPES, activeEntityCountTypeAndSubTypes);
metrics.addMetric(ENTITY, METRIC_ENTITY_DELETED_INCL_SUBTYPES, deletedEntityCountTypeAndSubTypes);
metrics.addMetric(ENTITY, METRIC_ENTITY_SHELL_INCL_SUBTYPES, shellEntityCountTypeAndSubTypes);
metrics.addMetric(TAG, METRIC_ENTITIES_PER_TAG, taggedEntityCount);
metrics.addMetric(SYSTEM, METRIC_MEMORY, AtlasMetricJVMUtil.getMemoryDetails());
metrics.addMetric(SYSTEM, METRIC_OS, AtlasMetricJVMUtil.getSystemInfo());
metrics.addMetric(SYSTEM, METRIC_RUNTIME, AtlasMetricJVMUtil.getRuntimeInfo());
return metrics;
}
private long getTypeCount(String typeName, Status status) {
Long ret = null;
String indexQuery = indexSearchPrefix + "\"" + ENTITY_TYPE_PROPERTY_KEY + "\" : (%s)" + AND_STR +
indexSearchPrefix + "\"" + STATE_PROPERTY_KEY + "\" : (%s)";
indexQuery = String.format(indexQuery, typeName, status.name());
try {
ret = atlasGraph.indexQuery(VERTEX_INDEX, indexQuery).vertexTotals();
}catch (Exception e){
LOG.error("Failed fetching using indexQuery: " + e.getMessage());
}
return ret == null ? 0L : ret;
}
private long getTypeShellCount(String typeName) {
Long ret = null;
String indexQuery = indexSearchPrefix + "\"" + ENTITY_TYPE_PROPERTY_KEY + "\" : (%s)" + AND_STR +
indexSearchPrefix + "\"" + IS_INCOMPLETE_PROPERTY_KEY + "\" : " + INCOMPLETE_ENTITY_VALUE.intValue();
indexQuery = String.format(indexQuery, typeName);
try {
ret = atlasGraph.indexQuery(VERTEX_INDEX, indexQuery).vertexTotals();
}catch (Exception e){
LOG.error("Failed fetching using indexQuery: " + e.getMessage());
}
return ret == null ? 0L : ret;
}
private int getAllTypesCount() {
Collection<String> allTypeNames = typeRegistry.getAllTypeNames();
return CollectionUtils.isNotEmpty(allTypeNames) ? allTypeNames.size() : 0;
}
private int getAllTagsCount() {
Collection<String> allTagNames = typeRegistry.getAllClassificationDefNames();
return CollectionUtils.isNotEmpty(allTagNames) ? allTagNames.size() : 0;
}
private AtlasTypesDef getTypesDef() {
AtlasTypesDef ret = new AtlasTypesDef();
Collection<AtlasEntityDef> entityDefs = typeRegistry.getAllEntityDefs();
if (CollectionUtils.isNotEmpty(entityDefs)) {
for(AtlasEntityDef entityDef : entityDefs) {
if(!(CollectionUtils.isNotEmpty(entityDef.getSuperTypes()) &&
entityDef.getSuperTypes().contains(Constants.TYPE_NAME_INTERNAL))) {
ret.getEntityDefs().add(entityDef);
}
}
}
Collection<AtlasClassificationDef> classificationTypes = typeRegistry.getAllClassificationDefs();
if (CollectionUtils.isNotEmpty(classificationTypes)) {
ret.getClassificationDefs().addAll(classificationTypes);
}
AtlasAuthorizationUtils.filterTypesDef(new AtlasTypesDefFilterRequest(ret));
return ret;
}
}