Package org.apache.sirona.reporting.web.plugin.api.graph

Source Code of org.apache.sirona.reporting.web.plugin.api.graph.Graphs

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.sirona.reporting.web.plugin.api.graph;

import org.apache.sirona.Role;
import org.apache.sirona.configuration.Configuration;
import org.apache.sirona.configuration.ioc.IoCs;
import org.apache.sirona.repositories.Repository;
import org.apache.sirona.store.gauge.CollectorGaugeDataStore;
import org.apache.sirona.store.gauge.GaugeValuesRequest;
import org.apache.sirona.util.Environment;

import java.awt.Color;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;

// a helper class to generate JSon (without dependencies) from gauges to plot graphes
public class Graphs {
    public static final String DEFAULT_COLOR = "#317eac";

    private static final int MAX_POINTS = Configuration.getInteger(Configuration.CONFIG_PROPERTY_PREFIX + "reporting.graph.max-points", 200) - 1;

    private static final Random RANDOM = new Random(System.currentTimeMillis());
    private static final int MAX_COLOR = 256;

    // default 5 colors, will grow automatically if more is needed. We need to keep same color between 2 refreshing
    private static final Collection<String> COLORS = new CopyOnWriteArrayList<String>(new String[] {
        generateColor(), generateColor(), generateColor(), generateColor(), generateColor()
    });

    public static String toJson(final String label, final String color, final SortedMap<Long, Double> data) {
        return "{\"label\":\"" + label + "\",\"color\":\"" + color + "\",\"data\": " + toJson(data) + "}";
    }

    public static String toJson(final SortedMap<Long, Double> data) { // helper for gauges
        final StringBuilder builder = new StringBuilder().append("[");
        final Iterator<Map.Entry<Long,Double>> iterator = data.entrySet().iterator();
        while (iterator.hasNext()) {
            final Map.Entry<Long, Double> entry = iterator.next();
            builder.append("[").append(entry.getKey()).append(", ").append(entry.getValue()).append("]");
            if (iterator.hasNext()) {
                builder.append(", ");
            }
        }
        return builder.append("]").toString();
    }

    private static String generateColor() {
        int red, green, blue;
        synchronized (RANDOM) {
            red = RANDOM.nextInt(MAX_COLOR);
            green = RANDOM.nextInt(MAX_COLOR);
            blue = RANDOM.nextInt(MAX_COLOR);
        }

        final Color color = new Color(red, green, blue);
        final String hexString = Integer.toHexString(color.getRGB());
        return "#" + hexString.substring(2, hexString.length());
    }

    public static String generateReport(final String label, final Role role, final long start, final long end) {
        if (!Environment.isCollector()) {
            final SortedMap<Long, Double> gaugeValues = Repository.INSTANCE.getGaugeValues(start, end, role);
            return "[" + Graphs.toJson(label, Graphs.DEFAULT_COLOR, aggregate(gaugeValues)) + "]";
        }

        final CollectorGaugeDataStore gaugeStore = IoCs.findOrCreateInstance(CollectorGaugeDataStore.class);
        final Iterator<String> markers = gaugeStore.markers().iterator();
        final StringBuilder builder = new StringBuilder("[");
        final Iterator<String> colors = COLORS.iterator();
        while (markers.hasNext()) {
            final String marker = markers.next();
            final String color;
            if (colors.hasNext()) {
                color = colors.next();
            } else {
                color = generateColor();
                COLORS.add(color);
            }

            final SortedMap<Long, Double> gaugeValues = gaugeStore.getGaugeValues(new GaugeValuesRequest(start, end, role), marker);
            builder.append(
                toJson(
                    label + " (" + marker + ")",
                    color,
                    aggregate(gaugeValues)
                )
            );
            if (markers.hasNext()) {
                builder.append(",");
            }
        }
        return builder.append("]").toString();
    }

    private static SortedMap<Long, Double> aggregate(final SortedMap<Long, Double> gaugeValues) {
        if (gaugeValues.size() < MAX_POINTS || !TreeMap.class.isInstance(gaugeValues)) {
            return gaugeValues;
        }

        final long min = gaugeValues.keySet().iterator().next();
        final long max = Number.class.cast(TreeMap.class.cast(gaugeValues).lastKey()).longValue();
        final long step = (long) ((max - min) * 1. / MAX_POINTS);

        final SortedMap<Long, Double> aggregation = new TreeMap<Long, Double>();
        double currentValue = 0;
        long switchValue = min + step;
        long number = 0;
        for (final Map.Entry<Long, Double> entry : gaugeValues.entrySet()) {
            final long key = entry.getKey();
            double value = entry.getValue();
            if (value == Double.NaN) {
                value = 0;
            }

            if (key < switchValue) {
                currentValue += value;
                number++;
            } else {
                aggregation.put(switchValue, currentValue / Math.max(1, number));
                switchValue += step;
                number = 0;
                currentValue = value;
            }
        }
        aggregation.put(switchValue, currentValue / Math.max(1, number));
        return aggregation;
    }

    private Graphs() {
        // no-op
    }
}
TOP

Related Classes of org.apache.sirona.reporting.web.plugin.api.graph.Graphs

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.