com.attribyte.essem.MGraphResponseGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.attribyte.essem.MGraphResponseGenerator.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.Fields;
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.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.text.SimpleDateFormat;
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.graphIgnoreProperties;

public class MGraphResponseGenerator extends ESResponseGenerator {

    /**
     * The date-time format.
     */
    private static final String DT_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Override
    public boolean generateGraph(GraphQuery graphQuery, Response esResponse, EnumSet<Option> options,
            RateUnit rateUnit, HttpServletResponse response) throws IOException {

        ObjectNode esResponseObject = mapper
                .readTree(parserFactory.createParser(esResponse.getBody().toByteArray()));

        ArrayNode targetGraph = JsonNodeFactory.instance.arrayNode();
        List<String> fields = ImmutableList.copyOf(graphQuery.searchRequest.fields);

        if (graphQuery.isAggregation) {
            JsonNode aggregations = esResponseObject.get("aggregations");
            if (aggregations != null && aggregations.isObject()) {
                String error = parseGraphAggregation(aggregations, fields, options, rateUnit, targetGraph);
                if (error != null) {
                    response.sendError(500, error);
                    return false;
                } else {
                    generateGraph(targetGraph, response);
                    return true;
                }
            } else {
                response.sendError(500, "No graph!");
                return false;
            }
        } else {
            parseGraph(esResponseObject, fields, options, rateUnit, targetGraph);
            generateGraph(targetGraph, 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, EnumSet<Option> options,
            RateUnit rateUnit, ArrayNode targetGraph) {

        DateTimeFormatter parser = ISODateTimeFormat.basicDateTime();
        SimpleDateFormat formatter = new SimpleDateFormat(DT_FORMAT);

        Map<MetricKey, List<ObjectNode>> 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) {
                        ObjectNode outObj = mapper.createObjectNode();
                        DateTime timestamp = parser.parseDateTime(getStringField(fieldsObj, "ts"));
                        outObj.put("timestamp", timestamp.getMillis());
                        outObj.put("date", formatter.format(timestamp.getMillis()));
                        MetricKey key = new MetricKey(getStringField(fieldsObj, "name"),
                                getStringField(fieldsObj, "application"), getStringField(fieldsObj, "host"),
                                getStringField(fieldsObj, "instance"));

                        Iterator<Map.Entry<String, JsonNode>> fieldIter = fieldsObj.fields();
                        while (fieldIter.hasNext()) {
                            Map.Entry<String, JsonNode> currField = fieldIter.next();
                            if (!graphIgnoreProperties.contains(currField.getKey())) {
                                JsonNode currValueNode = currField.getValue();
                                if (currValueNode.isArray() && currValueNode.size() > 0) {
                                    setFieldValue(rateUnit, outObj, currField.getKey(), currValueNode.get(0));
                                } else if (!currValueNode.isArray()) {
                                    setFieldValue(rateUnit, outObj, currField.getKey(), currValueNode);
                                }
                            }
                        }

                        List<ObjectNode> graph = outputGraphs.get(key);
                        if (graph == null) {
                            graph = Lists.newArrayListWithExpectedSize(1024);
                            outputGraphs.put(key, graph);
                        }
                        graph.add(outObj);
                    }
                }
            }
        }

        if (outputGraphs.size() == 1) {
            List<ObjectNode> graphNodes = outputGraphs.values().iterator().next();
            for (ObjectNode outObj : graphNodes) {
                targetGraph.add(outObj);
            }
        } else {
            for (Map.Entry<MetricKey, List<ObjectNode>> graphEntry : outputGraphs.entrySet()) {
                MetricKey key = graphEntry.getKey();
                ObjectNode outputGraphNode = targetGraph.addObject();
                outputGraphNode.put("name", key.name);
                outputGraphNode.put("application", key.application);
                outputGraphNode.put("host", key.host);
                outputGraphNode.put("instance", key.instance);
                ArrayNode currOutputGraph = outputGraphNode.putArray("graph");
                for (ObjectNode outObj : graphEntry.getValue()) {
                    currOutputGraph.add(outObj);
                }
            }
        }
    }

    private String parseGraphAggregation(JsonNode sourceParent, List<String> fields, EnumSet<Option> options,
            RateUnit rateUnit, 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";
                }

                String error = parseGraphAggregation(bucketObj, fields, options, rateUnit, targetGraph);
                if (error != null) {
                    return error;
                }
            }
            return null;
        } else {
            SimpleDateFormat formatter = new SimpleDateFormat(DT_FORMAT);
            boolean allowEmptyBins = options.contains(Option.EMPTY_BINS);

            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";
                }

                JsonNode docCountNode = bucketObj.get(SAMPLES_KEY);
                long samples = docCountNode != null ? docCountNode.asLong() : 0L;

                if (allowEmptyBins || samples > 0L) {

                    ObjectNode sampleObj = targetGraph.addObject();
                    sampleObj.put("timestamp", keyNode.asLong());
                    sampleObj.put("date", formatter.format(keyNode.asLong()));
                    sampleObj.put("samples", samples);

                    for (String field : fields) {
                        JsonNode fieldObj = bucketObj.get(field);
                        if (fieldObj != null) {
                            JsonNode valueNode = fieldObj.get("value");
                            if (valueNode != null) {
                                if (!valueNode.isNull()) {
                                    setFieldValue(rateUnit, sampleObj, field, valueNode);
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }
    }

    /**
     * Sets a field value, converting rates, if requested.
     * @param rateUnit The rate unit.
     * @param parentObj The parent to which the field is added.
     * @param field The field name.
     * @param valueNode The input value node.
     */
    private static void setFieldValue(RateUnit rateUnit, ObjectNode parentObj, String field, JsonNode valueNode) {

        if (rateUnit == ResponseGenerator.RAW_RATE_UNIT) {
            parentObj.set(field, valueNode);
        } else {
            if (!Fields.rateFields.contains(field)) {
                parentObj.set(field, valueNode);
            } else {
                parentObj.put(field, valueNode.doubleValue() * rateUnit.mult);
            }
        }
    }
}