com.attribyte.essem.DefaultResponseGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.attribyte.essem.DefaultResponseGenerator.java

Source

/*
 * Copyright 2014 Attribyte, LLC
 *
 * 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 com.attribyte.essem;

import com.attribyte.essem.model.graph.MetricKey;
import com.attribyte.essem.query.GraphQuery;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.attribyte.api.http.Response;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static com.attribyte.essem.util.Util.getStringField;
import static com.attribyte.essem.util.Util.getFieldNode;
import static com.attribyte.essem.util.Util.graphIgnoreProperties;
import static com.attribyte.essem.query.Fields.rateFields;

public class DefaultResponseGenerator extends ESResponseGenerator {

    @Override
    public boolean generateGraph(GraphQuery graphQuery, Response esResponse, EnumSet<Option> options,
            RateUnit rateUnit, HttpServletResponse response) throws IOException {
        ObjectNode jsonObject = mapper.readTree(parserFactory.createParser(esResponse.getBody().toByteArray()));

        ObjectNode responseObject = JsonNodeFactory.instance.objectNode();
        List<String> fields = ImmutableList.copyOf(graphQuery.searchRequest.fields);
        ObjectNode targetMeta = JsonNodeFactory.instance.objectNode();
        ArrayNode targetGraphs = responseObject.putArray("graphs");

        if (graphQuery.range.expression != null) {
            targetMeta.put("range", graphQuery.range.expression);
        }

        if (graphQuery.range.startTimestamp > 0L) {
            targetMeta.put("rangeStartTimestamp", graphQuery.range.startTimestamp);
        }

        if (graphQuery.range.endTimestamp > 0L) {
            targetMeta.put("rangeEndTimestamp", graphQuery.range.endTimestamp);
        }

        JsonNode aggregations = jsonObject.get("aggregations");
        if (aggregations != null && aggregations.isObject()) {
            ArrayNode metaFields = targetMeta.putArray("fields");
            metaFields.add("timestamp");
            metaFields.add("samples");
            for (String field : fields) {
                metaFields.add(field);
            }

            if (graphQuery.downsampleInterval != null) {
                targetMeta.put("downsampledTo", graphQuery.downsampleInterval);
            }

            if (graphQuery.downsampleFunction != null) {
                targetMeta.put("downsampledWith", graphQuery.downsampleFunction);
            }

            String error = parseGraphAggregation(aggregations, fields, rateUnit, targetMeta, targetGraphs);
            if (error == null) {
                generateGraph(responseObject, response);
                return true;
            } else {
                response.sendError(500, error);
                return false;
            }
        } else {
            ArrayNode metaFields = targetMeta.putArray("fields");
            metaFields.add("timestamp");
            metaFields.add("samples");
            for (String field : fields) {
                if (!graphIgnoreProperties.contains(field)) {
                    metaFields.add(field);
                }
            }
            parseGraph(jsonObject, fields, rateUnit, targetMeta, targetGraphs);
            generateGraph(responseObject, response);
            return true;
        }
    }

    private void generateGraph(JsonNode responseObject, HttpServletResponse response) throws IOException {
        response.setContentType(JSON_CONTENT_TYPE_HEADER);
        response.setStatus(HttpServletResponse.SC_OK);
        response.getOutputStream().write(responseObject.toString().getBytes("UTF-8"));
        response.getOutputStream().flush();
    }

    protected void parseGraph(JsonNode sourceParent, List<String> fields, RateUnit rateUnit, ObjectNode targetMeta,
            ArrayNode targetGraph) {

        DateTimeFormatter parser = ISODateTimeFormat.basicDateTime();

        Map<MetricKey, ArrayNode> outputGraphs = Maps.newHashMapWithExpectedSize(4);

        JsonNode hitsObj = sourceParent.get("hits");
        if (hitsObj != null) {
            JsonNode hitsArr = hitsObj.get("hits");
            if (hitsArr != null) {

                for (JsonNode hitObj : hitsArr) {
                    JsonNode fieldsObj = hitObj.get("fields");
                    if (fieldsObj != null) {
                        MetricKey key = new MetricKey(getStringField(fieldsObj, "name"),
                                getStringField(fieldsObj, "application"), getStringField(fieldsObj, "host"),
                                getStringField(fieldsObj, "instance"));

                        ArrayNode samplesArr = outputGraphs.get(key);
                        if (samplesArr == null) {
                            ObjectNode graphObj = targetGraph.addObject();
                            addMeta(key, graphObj, targetMeta);
                            samplesArr = graphObj.putArray("samples");
                            outputGraphs.put(key, samplesArr);
                        }

                        ArrayNode sampleArr = samplesArr.addArray();

                        DateTime timestamp = parser.parseDateTime(getStringField(fieldsObj, "ts"));
                        sampleArr.add(timestamp.getMillis());
                        sampleArr.add(1); //Samples..

                        for (String field : fields) {
                            if (!graphIgnoreProperties.contains(field)) {
                                JsonNode fieldNode = getFieldNode(fieldsObj, field);
                                if (rateUnit == RAW_RATE_UNIT || fieldNode == null || !rateFields.contains(field)) {
                                    if (fieldNode != null) {
                                        sampleArr.add(fieldNode);
                                    } else {
                                        sampleArr.addNull();
                                    }
                                } else {
                                    sampleArr.add(fieldNode.doubleValue() * rateUnit.mult);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    protected String parseGraphAggregation(JsonNode sourceParent, List<String> fields, RateUnit rateUnit,
            ObjectNode targetMeta, ArrayNode targetGraph) {

        Iterator<Map.Entry<String, JsonNode>> iter = sourceParent.fields();
        Map.Entry<String, JsonNode> aggregation = null;

        while (iter.hasNext()) {
            aggregation = iter.next();
            if (aggregation.getValue().isObject()) {
                break;
            } else {
                aggregation = null;
            }
        }

        if (aggregation == null) {
            return "Aggregation is invalid";
        }

        String bucketName = aggregation.getKey();

        JsonNode obj = aggregation.getValue();
        JsonNode bucketsObj = obj.get("buckets");
        if (bucketsObj == null || !bucketsObj.isArray()) {
            return "Aggregation is invalid";
        }

        if (keyComponents.contains(bucketName)) {
            for (final JsonNode bucketObj : bucketsObj) {
                if (!bucketObj.isObject()) {
                    return "Aggregation is invalid";
                }

                JsonNode keyNode = bucketObj.get(KEY_NODE_KEY);
                if (keyNode == null) {
                    return "Aggregation is invalid";
                }

                targetMeta.put(translateBucketName(bucketName), keyNode.asText());
                String error = parseGraphAggregation(bucketObj, fields, rateUnit, targetMeta.deepCopy(),
                        targetGraph);
                if (error != null) {
                    return error;
                }
            }
            return null;
        } else {
            ObjectNode graphObj = targetGraph.addObject();
            addAggregationMeta(graphObj, targetMeta);

            ArrayNode samplesArr = graphObj.putArray("samples");

            for (final JsonNode bucketObj : bucketsObj) {
                if (!bucketObj.isObject()) {
                    return "Aggregation is invalid";
                }

                JsonNode keyNode = bucketObj.get(KEY_NODE_KEY);
                if (keyNode == null) {
                    return "Aggregation is invalid";
                }

                ArrayNode sampleArr = samplesArr.addArray();
                sampleArr.add(keyNode.asLong());
                JsonNode docCountNode = bucketObj.get(SAMPLES_KEY);
                long samples = docCountNode != null ? docCountNode.asLong() : 0L;
                sampleArr.add(samples);

                for (String field : fields) {
                    JsonNode fieldObj = bucketObj.get(field);
                    if (fieldObj != null) {
                        JsonNode valueNode = fieldObj.get("value");
                        if (rateUnit == RAW_RATE_UNIT || valueNode == null || !rateFields.contains(field)) {
                            if (valueNode != null) {
                                sampleArr.add(valueNode);
                            } else {
                                sampleArr.add(0L);
                            }
                        } else {
                            sampleArr.add(valueNode.doubleValue() * rateUnit.mult);
                        }
                    } else {
                        sampleArr.add(0L);
                    }
                }
            }

            return null;
        }
    }

    private static final Joiner keyJoiner = Joiner.on('.').skipNulls();

    /**
     * Adds the metadata to a graph built from an ES aggregation.
     * @param graphObj The graph object.
     * @param targetMeta The target (input) meta.
     */
    private void addAggregationMeta(final ObjectNode graphObj, final ObjectNode targetMeta) {
        ObjectNode meta = targetMeta.deepCopy();

        List<String> metaList = Lists.newArrayListWithExpectedSize(4);
        if (meta.has("application")) {
            metaList.add(meta.get("application").asText());
        }
        if (meta.has("host")) {
            metaList.add(meta.get("host").asText());
        }

        if (meta.has("instance")) {
            metaList.add(meta.get("instance").asText());
        }

        if (meta.has("name")) {
            metaList.add(meta.get("name").asText());
        }

        meta.put("key", keyJoiner.join(metaList));

        graphObj.set("meta", meta);
    }

    /**
     * Adds the metadata to a graph built from an ES aggregation.
     * @param key The graph key.
     * @param graphObj The node to which the meta will be added.
     * @param targetMeta The target (input) meta.
     */
    private void addMeta(final MetricKey key, final ObjectNode graphObj, final ObjectNode targetMeta) {
        ObjectNode meta = targetMeta.deepCopy();

        List<String> metaList = Lists.newArrayListWithExpectedSize(4);
        if (!Strings.isNullOrEmpty(key.application)) {
            meta.put("application", key.application);
            metaList.add(key.application);
        }
        if (!Strings.isNullOrEmpty(key.host)) {
            meta.put("host", key.host);
            metaList.add(key.host);
        }
        if (!Strings.isNullOrEmpty(key.instance)) {
            meta.put("instance", key.instance);
            metaList.add(key.instance);
        }
        if (!Strings.isNullOrEmpty(key.name)) {
            meta.put("name", key.name);
            metaList.add(key.name);
        }

        meta.put("key", keyJoiner.join(metaList));

        graphObj.set("meta", meta);
    }

}