All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mantledillusion.metrics.trail.ElasticMetricsPersistor Maven / Gradle / Ivy

package com.mantledillusion.metrics.trail;

import com.mantledillusion.metrics.trail.api.Event;
import com.mantledillusion.metrics.trail.api.Measurement;
import com.mantledillusion.metrics.trail.api.EventFields;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;
import java.util.UUID;

/**
 * {@link MetricsConsumer} implementation that is able to persist consumed {@link Event}s into an Elastic database.
 */
public class ElasticMetricsPersistor implements MetricsConsumer {

    public static final String DEFAULT_INDEX_PREFIX = "metrics.";

    /**
     * Describes the modes the elastic index to push to is determined by.
     */
    public enum IndexMode {

        /**
         * The index will be the {@link Event}'s identifier, prepended by the prefix currently set.
         */
        IDENTIFIER,

        /**
         * The index will be the {@link Event}'s consumer's ID, prepended by the prefix currently set.
         */
        CONSUMER,

        /**
         * The index will be just the prefix by itself.
         */
        STATIC
    }

    private final RestHighLevelClient client;
    private IndexMode indexMode = IndexMode.IDENTIFIER;
    private String indexPrefix = DEFAULT_INDEX_PREFIX;

    private ElasticMetricsPersistor(RestHighLevelClient client) {
        this.client = client;
    }

    /**
     * Returns the mode determining the index the metrics are pushed to.
     * 

* Set to {@link IndexMode#IDENTIFIER} by default. * * @return The index mode, never null */ public IndexMode getIndexMode() { return this.indexMode; } /** * Returns the prefix prepended to metric identifiers when used for an elastic index. *

* Set to {@value #DEFAULT_INDEX_PREFIX} by default. * * @return The prefix, never null */ public String getIndexPrefix() { return this.indexPrefix; } /** * Sets the index mode and prefix to use when pushing metrics to elastic. * * @param mode The mode to use when determining the index; might not be null. * @param prefix The prefix to prepend to the index determined; might be null unless the mode is {@link IndexMode#STATIC}. */ public void setIndexMode(IndexMode mode, String prefix) { prefix = prefix == null ? "" : prefix; if (mode == null) { throw new IllegalArgumentException("Cannot set a null index mode"); } else if (mode == IndexMode.STATIC && prefix.isEmpty()) { throw new IllegalArgumentException("Cannot use an empty prefix with the STATIC index mode"); } this.indexMode = mode; this.indexPrefix = prefix; } @Override public void consume(String consumerId, UUID correlationId, Event event) throws IOException { XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .field(EventFields.CONSUMER_ID.getName(), consumerId) .field(EventFields.CORRELATION_ID.getName(), correlationId.toString()) .field(EventFields.IDENTIFIER.getName(), event.getIdentifier()); if (event.getMeasurements() != null) { for (Measurement measurement : event.getMeasurements()) { String name = EventFields.MEASUREMENTS.getName() + '.' + measurement.getKey(); switch (measurement.getType()) { case BOOLEAN: builder.field(name, (Boolean) measurement.parseValue()); break; case SHORT: builder.field(name, (Short) measurement.parseValue()); break; case INTEGER: builder.field(name, (Integer) measurement.parseValue()); break; case LONG: builder.field(name, (Long) measurement.parseValue()); break; case FLOAT: builder.field(name, (Float) measurement.parseValue()); break; case DOUBLE: builder.field(name, (Double) measurement.parseValue()); break; case BIGINTEGER: builder.field(name, (BigInteger) measurement.parseValue()); break; case BIGDECIMAL: builder.field(name, (BigDecimal) measurement.parseValue()); break; case LOCAL_DATE: builder.field(name, (LocalDate) measurement.parseValue()); break; case LOCAL_TIME: builder.field(name, (LocalTime) measurement.parseValue()); break; case LOCAL_DATETIME: builder.field(name, (LocalDateTime) measurement.parseValue()); break; case ZONED_DATETIME: builder.field(name, (ZonedDateTime) measurement.parseValue()); break; default: builder.field(name, measurement.getValue()); break; } } } String index = this.indexPrefix; switch (this.indexMode) { case IDENTIFIER: index += event.getIdentifier(); break; case CONSUMER: index = consumerId; break; } this.client.index(new IndexRequest() .index(index) .source(builder .timeField(EventFields.TIMESTAMP.getName(), event.getTimestamp()) .endObject()), RequestOptions.DEFAULT); } /** * Factory method for {@link ElasticMetricsPersistor}s. *

* Will use the given {@link RestHighLevelClient} to persist consumed metrics. * * @param client The {@link RestHighLevelClient} to persist into; might not be null. * @return A new {@link ElasticMetricsPersistor} instance, never null */ public static ElasticMetricsPersistor from(RestHighLevelClient client) { if (client == null) { throw new IllegalArgumentException("Cannot create a metrics persistor from a null client."); } return new ElasticMetricsPersistor(client); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy