org.ventiv.docker.manager.metrics.store.InfluxDbAdditionalMetricsStore.java Source code

Java tutorial

Introduction

Here is the source code for org.ventiv.docker.manager.metrics.store.InfluxDbAdditionalMetricsStore.java

Source

/**
 * Copyright (c) 2014 - 2016 Ventiv Technology
 *
 * Licensed 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
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.ventiv.docker.manager.metrics.store;

import org.influxdb.dto.Point;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.springframework.data.influxdb.InfluxDBTemplate;
import org.ventiv.docker.manager.model.ServiceInstance;
import org.ventiv.docker.manager.model.metrics.AdditionalMetricsStorage;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Additional Metrics Store backed by InfluxDB (A Time Series Database)
 */
public class InfluxDbAdditionalMetricsStore extends AbstractAdditionalMetricsStore {

    private InfluxDBTemplate<Point> template;

    public InfluxDbAdditionalMetricsStore(InfluxDBTemplate<Point> template) {
        this.template = template;
    }

    @Override
    public List<AdditionalMetricsStorage> getAdditionalMetricsBetween(ServiceInstance serviceInstance,
            Long startTime, Long endTime) {
        StringBuilder queryStr = new StringBuilder("select * from ").append(serviceInstance.getName())
                .append(" where ");

        if (startTime != null)
            queryStr.append("time > ").append(startTime).append("ms AND");

        if (endTime != null)
            queryStr.append("time < ").append(endTime).append("ms AND");

        queryStr.append("tierName = '").append(serviceInstance.getTierName()).append("' ")
                .append("AND environmentName = '").append(serviceInstance.getEnvironmentName()).append("' ")
                .append("AND applicationId = '").append(serviceInstance.getApplicationId()).append("' ")
                .append("AND \"name\" = '").append(serviceInstance.getName()).append("' ")
                .append("AND instanceNumber = '").append(serviceInstance.getInstanceNumber()).append("' ");

        Query q = new Query(queryStr.toString(), template.getDatabase());
        QueryResult result = template.query(q, TimeUnit.MILLISECONDS);

        Map<Date, AdditionalMetricsStorage> additionalMetrics = new HashMap<>();
        for (QueryResult.Result queryResult : result.getResults()) {
            for (QueryResult.Series series : queryResult.getSeries()) {
                for (List<Object> values : series.getValues()) {
                    Date time = new Date(((Number) values.get(0)).longValue());
                    for (int i = 1; i < values.size(); i++) {
                        Object value = values.get(i);
                        if (value instanceof Double) {
                            AdditionalMetricsStorage additionalMetric = additionalMetrics.get(time);
                            String additionalMetricName = series.getColumns().get(i);

                            if (additionalMetric == null) {
                                additionalMetric = new AdditionalMetricsStorage();
                                additionalMetric.setId(time.getTime());
                                additionalMetric.setTimestamp(time.getTime());
                                additionalMetric.setAdditionalMetrics(new HashMap<String, BigDecimal>());
                                additionalMetrics.put(time, additionalMetric);
                            }

                            additionalMetric.getAdditionalMetrics().put(additionalMetricName,
                                    new BigDecimal((Double) value));
                        }
                    }
                }
            }
        }

        return new ArrayList<>(additionalMetrics.values());
    }

    @Override
    public void storeAdditionalMetrics(ServiceInstance serviceInstance,
            AdditionalMetricsStorage additionalMetricsStorage) {
        if (additionalMetricsStorage.getAdditionalMetrics().size() == 0)
            return;

        List<Point> points = new ArrayList<>(1);
        Point.Builder p = Point.measurement(serviceInstance.getName()).time(additionalMetricsStorage.getTimestamp(),
                TimeUnit.MILLISECONDS);

        if (serviceInstance.getTierName() != null)
            p.tag("tierName", serviceInstance.getTierName());

        if (serviceInstance.getEnvironmentName() != null)
            p.tag("environmentName", serviceInstance.getEnvironmentName());

        if (serviceInstance.getEnvironmentDescription() != null)
            p.tag("environmentDescription", serviceInstance.getEnvironmentDescription());

        if (serviceInstance.getApplicationId() != null)
            p.tag("applicationId", serviceInstance.getApplicationId());

        if (serviceInstance.getApplicationDescription() != null)
            p.tag("applicationDescription", serviceInstance.getApplicationDescription());

        if (serviceInstance.getName() != null)
            p.tag("name", serviceInstance.getName());

        if (serviceInstance.getServiceDescription() != null)
            p.tag("serviceDescription", serviceInstance.getServiceDescription());

        if (serviceInstance.getServerName() != null)
            p.tag("serverName", serviceInstance.getServerName());

        if (serviceInstance.getInstanceNumber() != null)
            p.tag("instanceNumber", serviceInstance.getInstanceNumber().toString());

        if (serviceInstance.getContainerId() != null)
            p.tag("containerId", serviceInstance.getContainerId());

        if (serviceInstance.getContainerImage() != null
                && serviceInstance.getContainerImage().getRegistry() != null)
            p.tag("image.registry", serviceInstance.getContainerImage().getRegistry());

        if (serviceInstance.getContainerImage() != null
                && serviceInstance.getContainerImage().getNamespace() != null)
            p.tag("image.namespace", serviceInstance.getContainerImage().getNamespace());

        if (serviceInstance.getContainerImage() != null
                && serviceInstance.getContainerImage().getRepository() != null)
            p.tag("image.repository", serviceInstance.getContainerImage().getRepository());

        if (serviceInstance.getContainerImage() != null && serviceInstance.getContainerImage().getTag() != null)
            p.tag("image.tag", serviceInstance.getContainerImage().getTag());

        for (Map.Entry<String, BigDecimal> e : additionalMetricsStorage.getAdditionalMetrics().entrySet()) {
            p.field(e.getKey(), e.getValue());
        }

        points.add(p.build());
        template.write(points);
    }

    @Override
    public List<Map<String, Object>> getTimeSeries(String metricName, String serverName, String tierName,
            String environmentName, String applicationId, String serviceName, Integer instanceNumber,
            Long fromTimestamp, Long toTimestamp, String last, String groupTimeWindow) {
        StringBuilder queryString = new StringBuilder("select min(\"").append(metricName).append("\"), max(\"")
                .append(metricName).append("\"), mean(\"").append(metricName).append("\"), sum(\"")
                .append(metricName).append("\"), count(\"").append(metricName).append("\") from ").append('"')
                .append(serviceName).append('"').append(" WHERE ");

        if (serverName != null)
            queryString.append("serverName = '").append(serverName).append("' AND ");

        if (tierName != null)
            queryString.append("tierName = '").append(tierName).append("' AND ");

        if (environmentName != null)
            queryString.append("environmentName = '").append(environmentName).append("' AND ");

        if (applicationId != null)
            queryString.append("applicationId = '").append(applicationId).append("' AND ");

        if (instanceNumber != null)
            queryString.append("instanceNumber = '").append(instanceNumber).append("' AND ");

        // If 'Last' is populated, take it over 'fromTimestamp' / 'toTimeStamp'
        if (last != null)
            queryString.append("time > now() - ").append(groovyTimeCategoryToInfluxTime(last)).append(" ");
        else if (fromTimestamp != null && toTimestamp != null)
            queryString.append("time > ").append(fromTimestamp).append("ms AND time < ").append(toTimestamp)
                    .append("ms ");
        else if (fromTimestamp != null)
            queryString.append("time > ").append(fromTimestamp).append("ms ");

        queryString.append("group by time(").append(groovyTimeCategoryToInfluxTime(groupTimeWindow)).append(")");

        Query q = new Query(queryString.toString(), template.getDatabase());
        QueryResult result = template.query(q, TimeUnit.MILLISECONDS);

        List<Map<String, Object>> answer = new ArrayList<>();
        for (QueryResult.Result queryResult : result.getResults()) {
            if (queryResult != null && queryResult.getSeries() != null) {
                for (QueryResult.Series series : queryResult.getSeries()) {
                    for (List<Object> values : series.getValues()) {
                        Map<String, Object> point = new HashMap<>();
                        answer.add(point);

                        point.put("timestamp", ((Number) values.get(0)).longValue());
                        point.put("min", values.get(1));
                        point.put("max", values.get(2));
                        point.put("avg", values.get(3));
                        point.put("sum", values.get(4));
                        point.put("count", values.get(5));
                    }
                }
            }
        }

        return answer;
    }

    private String groovyTimeCategoryToInfluxTime(String groovyTimeCategory) {
        assert !groovyTimeCategory.contains("years");
        assert !groovyTimeCategory.contains("months");

        return groovyTimeCategory.replaceAll("weeks", "w").replaceAll("days", "d").replaceAll("hours", "h")
                .replaceAll("minutes", "m").replaceAll("seconds", "s").replaceAll("millis", "ms")
                .replaceAll("micros", "u").replaceAll("\\.", "");
    }

}