ddf.catalog.metrics.CatalogMetrics.java Source code

Java tutorial

Introduction

Here is the source code for ddf.catalog.metrics.CatalogMetrics.java

Source

/**
 * Copyright (c) Codice Foundation
 *
 * <p>This is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or any later version.
 *
 * <p>This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details. A copy of the GNU Lesser General Public
 * License is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 */
package ddf.catalog.metrics;

import com.codahale.metrics.Histogram;
import com.codahale.metrics.JmxReporter;
import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.SlidingTimeWindowReservoir;
import ddf.catalog.federation.FederationException;
import ddf.catalog.filter.FilterAdapter;
import ddf.catalog.operation.CreateResponse;
import ddf.catalog.operation.DeleteResponse;
import ddf.catalog.operation.ProcessingDetails;
import ddf.catalog.operation.QueryRequest;
import ddf.catalog.operation.QueryResponse;
import ddf.catalog.operation.ResourceResponse;
import ddf.catalog.operation.UpdateResponse;
import ddf.catalog.plugin.PluginExecutionException;
import ddf.catalog.plugin.PostIngestPlugin;
import ddf.catalog.plugin.PostQueryPlugin;
import ddf.catalog.plugin.PostResourcePlugin;
import ddf.catalog.plugin.PreQueryPlugin;
import ddf.catalog.plugin.StopProcessingException;
import ddf.catalog.source.SourceUnavailableException;
import ddf.catalog.source.UnsupportedQueryException;
import ddf.catalog.util.impl.Requests;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang.StringUtils;
import org.codice.ddf.configuration.SystemInfo;

/**
 * Catalog plug-in to capture metrics on catalog operations.
 *
 * @author Phillip Klinefelter
 */
public final class CatalogMetrics implements PreQueryPlugin, PostQueryPlugin, PostIngestPlugin, PostResourcePlugin {

    protected static final String EXCEPTIONS_SCOPE = "Exceptions";

    protected static final String QUERIES_SCOPE = "Queries";

    protected static final String INGEST_SCOPE = "Ingest";

    protected static final String RESOURCE_SCOPE = "Resource";

    protected final MetricRegistry metrics = new MetricRegistry();

    protected final JmxReporter reporter = JmxReporter.forRegistry(metrics).inDomain("ddf.metrics.catalog").build();

    protected final Histogram resultCount;

    protected final Meter exceptions;

    protected final Meter unsupportedQueryExceptions;

    protected final Meter sourceUnavailableExceptions;

    protected final Meter federationExceptions;

    protected final Meter queries;

    protected final Meter federatedQueries;

    protected final Meter comparisonQueries;

    protected final Meter spatialQueries;

    protected final Meter xpathQueries;

    protected final Meter fuzzyQueries;

    protected final Meter functionQueries;

    protected final Meter temporalQueries;

    protected final Meter createdMetacards;

    protected final Meter updatedMetacards;

    protected final Meter deletedMetacards;

    protected final Meter resourceRetrival;

    private final FilterAdapter filterAdapter;

    public CatalogMetrics(FilterAdapter filterAdapter) {

        this.filterAdapter = filterAdapter;

        resultCount = metrics.register(MetricRegistry.name(QUERIES_SCOPE, "TotalResults"),
                new Histogram(new SlidingTimeWindowReservoir(1, TimeUnit.MINUTES)));

        queries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE));
        federatedQueries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE, "Federated"));
        comparisonQueries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE, "Comparison"));
        spatialQueries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE, "Spatial"));
        xpathQueries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE, "Xpath"));
        fuzzyQueries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE, "Fuzzy"));
        temporalQueries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE, "Temporal"));
        functionQueries = metrics.meter(MetricRegistry.name(QUERIES_SCOPE, "Function"));

        exceptions = metrics.meter(MetricRegistry.name(EXCEPTIONS_SCOPE));
        unsupportedQueryExceptions = metrics.meter(MetricRegistry.name(EXCEPTIONS_SCOPE, "UnsupportedQuery"));
        sourceUnavailableExceptions = metrics.meter(MetricRegistry.name(EXCEPTIONS_SCOPE, "SourceUnavailable"));
        federationExceptions = metrics.meter(MetricRegistry.name(EXCEPTIONS_SCOPE, "Federation"));

        createdMetacards = metrics.meter(MetricRegistry.name(INGEST_SCOPE, "Created"));
        updatedMetacards = metrics.meter(MetricRegistry.name(INGEST_SCOPE, "Updated"));
        deletedMetacards = metrics.meter(MetricRegistry.name(INGEST_SCOPE, "Deleted"));

        resourceRetrival = metrics.meter(MetricRegistry.name(RESOURCE_SCOPE));

        reporter.start();
    }

    // PostQuery
    @Override
    public QueryResponse process(QueryResponse input) throws PluginExecutionException, StopProcessingException {
        resultCount.update(input.getHits());
        recordSourceQueryExceptions(input);

        return input;
    }

    // PreQuery
    @Override
    public QueryRequest process(QueryRequest input) throws PluginExecutionException, StopProcessingException {
        if (isFederated(input)) {
            federatedQueries.mark();
        }
        queries.mark();

        QueryTypeFilterDelegate queryType = new QueryTypeFilterDelegate();
        try {
            filterAdapter.adapt(input.getQuery(), queryType);
            if (queryType.isComparison()) {
                comparisonQueries.mark();
            }
            if (queryType.isSpatial()) {
                spatialQueries.mark();
            }
            if (queryType.isFuzzy()) {
                fuzzyQueries.mark();
            }
            if (queryType.isXpath()) {
                xpathQueries.mark();
            }
            if (queryType.isTemporal()) {
                temporalQueries.mark();
            }
            if (queryType.isFunction()) {
                functionQueries.mark();
            }
        } catch (UnsupportedQueryException e) {
            // ignore filters not supported by the QueryTypeFilterDelegate
        }

        return input;
    }

    // PostCreate
    @Override
    public CreateResponse process(CreateResponse input) throws PluginExecutionException {
        if (Requests.isLocal(input.getRequest())) {
            createdMetacards.mark(input.getCreatedMetacards().size());
        }
        return input;
    }

    // PostUpdate
    @Override
    public UpdateResponse process(UpdateResponse input) throws PluginExecutionException {
        if (Requests.isLocal(input.getRequest())) {
            updatedMetacards.mark(input.getUpdatedMetacards().size());
        }
        return input;
    }

    // PostDelete
    @Override
    public DeleteResponse process(DeleteResponse input) throws PluginExecutionException {
        if (Requests.isLocal(input.getRequest())) {
            deletedMetacards.mark(input.getDeletedMetacards().size());
        }
        return input;
    }

    // PostResource
    @Override
    public ResourceResponse process(ResourceResponse input)
            throws PluginExecutionException, StopProcessingException {
        resourceRetrival.mark();
        return input;
    }

    private void recordSourceQueryExceptions(QueryResponse response) {
        Set<ProcessingDetails> processingDetails = (Set<ProcessingDetails>) response.getProcessingDetails();

        if (processingDetails == null || processingDetails.iterator() == null) {
            return;
        }

        Iterator<ProcessingDetails> iterator = processingDetails.iterator();
        while (iterator.hasNext()) {
            ProcessingDetails next = iterator.next();
            if (next != null && next.getException() != null) {
                if (next.getException() instanceof UnsupportedQueryException) {
                    unsupportedQueryExceptions.mark();
                } else if (next.getException() instanceof SourceUnavailableException) {
                    sourceUnavailableExceptions.mark();
                } else if (next.getException() instanceof FederationException) {
                    federationExceptions.mark();
                }
                exceptions.mark();
            }
        }

        return;
    }

    private boolean isFederated(QueryRequest queryRequest) {
        Set<String> sourceIds = queryRequest.getSourceIds();

        if (queryRequest.isEnterprise()) {
            return true;
        } else if (sourceIds == null) {
            return false;
        } else {
            return (sourceIds.size() > 1)
                    || (sourceIds.size() == 1 && sourceIds.stream().noneMatch(StringUtils::isEmpty)
                            && !sourceIds.contains(SystemInfo.getSiteName()));
        }
    }
}