org.clevermore.monitor.client.servers.ServerStatsPopup.java Source code

Java tutorial

Introduction

Here is the source code for org.clevermore.monitor.client.servers.ServerStatsPopup.java

Source

/**
 * Copyright (C) 2013 Arman Gal
 *
 * 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.clevermore.monitor.client.servers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import org.clevermore.monitor.client.ServerWidgetService;
import org.clevermore.monitor.client.ServerWidgetServiceAsync;
import org.clevermore.monitor.client.utils.ClientStringFormatter;
import org.clevermore.monitor.client.widgets.DynamicLine;
import org.clevermore.monitor.client.widgets.ILineType;
import org.clevermore.monitor.client.widgets.MonitoringDynamicLinesChart;
import org.clevermore.monitor.client.widgets.MonitoringLineChart;
import org.clevermore.monitor.shared.ChartFeed;
import org.clevermore.monitor.shared.config.ClientConfigurations;
import org.clevermore.monitor.shared.config.Colors;
import org.clevermore.monitor.shared.runtime.CpuUtilizationChunk;
import org.clevermore.monitor.shared.runtime.MemoryState;
import org.clevermore.monitor.shared.runtime.MemoryUsage;
import org.clevermore.monitor.shared.runtime.RuntimeInfo;
import org.clevermore.monitor.shared.runtime.ThreadDump;
import org.clevermore.monitor.shared.servers.ConnectedServer;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.HasDirection.Direction;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.Widget;
import com.googlecode.gwt.charts.client.ColumnType;

public class ServerStatsPopup<CC extends ClientConfigurations> extends DialogBox {

    private final ServerWidgetServiceAsync service = GWT.create(ServerWidgetService.class);

    private MonitoringLineChart<Double, Long> cpuChart = new MonitoringLineChart<Double, Long>(
            new ILineType[] { ServersLineType.CPU }, "CPU%", "Time", "CPU Load");
    private MonitoringLineChart<Double, Long> sysLoadChart = new MonitoringLineChart<Double, Long>(
            new ILineType[] { ServersLineType.SYS_LOAD }, "SysLoadAvg", "Time", "System Load Average");
    private MonitoringLineChart<Double, Long> memoryChart = new MonitoringLineChart<Double, Long>(
            new ILineType[] { ServersLineType.MEMORY }, "Memory%", "Time", "Memory Usage");

    private MonitoringDynamicLinesChart<Long, Long> memoryDetailsChart = new MonitoringDynamicLinesChart<Long, Long>(
            "M.B.", "Time", "Memory Details");

    private FlowPanel fp = new FlowPanel();
    private FlowPanel cpu = new FlowPanel();
    private FlowPanel memory = new FlowPanel();
    private FlowPanel memoryDetails = new FlowPanel();
    private FlowPanel sysLoad = new FlowPanel();
    private FlowPanel details = new FlowPanel();

    private Integer serverCode;

    private Integer chunks = 30;
    private boolean showHeap = true;
    private boolean refresh = true;
    private LinkedList<MemoryUsage> memoryUsages;// local copy for fast refresh

    NativePreviewHandler globalKeyHandler = new NativePreviewHandler() {
        @Override
        public void onPreviewNativeEvent(NativePreviewEvent event) {
            NativeEvent ne = event.getNativeEvent();
            if (ne.getKeyCode() == 27) {//on Esc
                hide();
            }
        }
    };

    HandlerRegistration nativePreviewHandler = Event.addNativePreviewHandler(globalKeyHandler);

    public ServerStatsPopup(final Integer serverCode) {
        this.serverCode = serverCode;
        setAnimationEnabled(true);
        setModal(true);
        setSize("760px", "450px");
        setGlassEnabled(true);

        service.getConnectedServer(serverCode, new AsyncCallback<ConnectedServer>() {

            public void onSuccess(ConnectedServer cs) {
                fp.add(new HTML("<h1>Server:" + cs.getServerCode() + ", " + cs.getName() + "</h1>"));

                fp.add(new HTML(
                        "<h2>Up Time:" + ClientStringFormatter.formatMilisecondsToHours(cs.getUpTime()) + "</h2>"));

                String gcs = "";
                for (Double gch : cs.getGcHistories()) {
                    gcs += ClientStringFormatter.formatMillisShort(gch) + ";";
                }
                HTML tech = new HTML(
                        "<h2>Memory:" + ClientStringFormatter.formatMBytes(cs.getMemoryUsage().getUsed()) + " of "
                                + ClientStringFormatter.formatMBytes(cs.getMemoryUsage().getMax()) + " MB, Usage:"
                                + ClientStringFormatter.formatMillisShort(cs.getMemoryUsage().getPercentage())
                                + "%, GC Time:" + gcs + "</h2>");

                fp.add(tech);

                HTML info = new HTML("<h2>" + cs.getMoreInfo() + "</h2");
                fp.add(info);

                fp.getElement().setId("xxx");
                setWidget(fp);

                memoryChart.setStyleName("serverPopupChart");
                memory.add(memoryChart);

                memoryDetailsChart.setStyleName("serverPopupChart");
                final CheckBox heap = new CheckBox("Show Heap");
                heap.setValue(true);
                heap.addClickHandler(new ClickHandler() {

                    @Override
                    public void onClick(ClickEvent event) {
                        showHeap = heap.getValue();
                        if (memoryUsages != null) {
                            updateMemoryDetailsChart(memoryUsages);
                        }
                    }
                });
                memoryDetails.add(heap);
                memoryDetails.add(memoryDetailsChart);

                cpuChart.setStyleName("serverPopupChart");
                cpu.add(cpuChart);

                sysLoadChart.setStyleName("serverPopupChart");
                sysLoad.add(sysLoadChart);

                loadSecondPart();

            };

            @Override
            public void onFailure(Throwable caught) {
                Window.alert("Error loading server:" + caught.getMessage());
                Log.error("Error loading server:" + serverCode + ", Error:" + caught.getMessage(), caught);
                hide();
            }
        });

    }

    private void addRadioButtons(HorizontalPanel hp) {
        RadioButton r30m = getRadioButton("m30", 30);
        r30m.setValue(true);
        hp.add(r30m);
        hp.add(getRadioButton("1h", 60));
        hp.add(getRadioButton("2h", 120));
        hp.add(getRadioButton("6h", 360));
        hp.add(getRadioButton("12h", 720));
        hp.add(getRadioButton("1d", 1440));
    }

    private RadioButton getRadioButton(final String name, int chunksToSet) {
        RadioButton r = new RadioButton("chunks", name);
        r.getElement().setAttribute("chunks", "" + chunksToSet);
        r.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                Widget w = (Widget) event.getSource();
                chunks = Integer.valueOf(w.getElement().getAttribute("chunks"));
                getMemoryStats(chunks);
                getCpuStats(chunks);
                getExtraData(chunks);
            }
        });
        return r;
    }

    /**
     * for extending popups to add additional elements to the panel
     */
    public void addExtraElements(FlowPanel fp) {

    }

    public void loadSecondPart() {
        HorizontalPanel hp = new HorizontalPanel();
        Button threadDump = new Button("Get Thread Dump");
        hp.add(threadDump);
        addRadioButtons(hp);
        Button close = new Button("Close");
        hp.add(close);
        close.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                hide();
            }
        });

        hp.setWidth("100%");
        hp.setCellHorizontalAlignment(close, HorizontalAlignmentConstant.endOf(Direction.LTR));
        Style style = close.getElement().getStyle();
        style.setColor("orange");
        style.setFontWeight(FontWeight.BOLDER);
        fp.add(hp);
        fp.add(cpu);
        fp.add(memory);
        fp.add(memoryDetails);
        fp.add(sysLoad);
        addExtraElements(fp);
        fp.add(details);

        threadDump.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                final ThreadDumpPopup tdp = new ThreadDumpPopup();
                tdp.center();

                service.getThreadDump(serverCode, new AsyncCallback<ThreadDump>() {

                    @Override
                    public void onSuccess(ThreadDump result) {
                        tdp.setDump(result);
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                        tdp.setText("Can't get thread dump:" + caught.getMessage());
                    }
                });
            }
        });

        getMemoryStats(chunks);
        getCpuStats(chunks);

        service.getRuntimeInfo(serverCode, new AsyncCallback<RuntimeInfo>() {

            @Override
            public void onSuccess(RuntimeInfo result) {
                updateRuntimeInfo(result);
                int left = (Window.getClientWidth() - getOffsetWidth()) >> 1;
                setPopupPosition(Math.max(Window.getScrollLeft() + left, 0), 26);

            }

            @Override
            public void onFailure(Throwable caught) {
                Log.error("error while getting server cpu stats:" + caught.getMessage());

            }
        });

        getExtraData(chunks);

        RepeatingCommand refreshCommand = new RepeatingCommand() {

            @Override
            public boolean execute() {
                if (refresh) {
                    getMemoryStats(chunks);
                    getCpuStats(chunks);
                    getExtraData(chunks);
                    Log.debug("Reschedule refresh");
                }
                return refresh;
            }
        };
        Scheduler.get().scheduleFixedDelay(refreshCommand, 20000);
    }

    @Override
    public void center() {
        setSize("760px", "450px");

        super.center();

    }

    public void getExtraData(Integer chunks) {

    }

    @Override
    public void hide() {
        super.hide();
        refresh = false;
        nativePreviewHandler.removeHandler();
    }

    private void getCpuStats(int chunks) {
        service.getCpuUsageHistory(serverCode, chunks, new AsyncCallback<LinkedList<CpuUtilizationChunk>>() {

            @Override
            public void onSuccess(LinkedList<CpuUtilizationChunk> result) {
                updateCpuChart(result);
                updateSysLoadChart(result);
            }

            @Override
            public void onFailure(Throwable caught) {
                Log.error("error while getting server cpu stats:" + caught.getMessage());
            }
        });
    }

    private void getMemoryStats(int chunks) {
        service.getMemoryStats(serverCode, chunks, new AsyncCallback<LinkedList<MemoryUsage>>() {

            @Override
            public void onSuccess(LinkedList<MemoryUsage> result) {
                memoryUsages = result;
                updateMemoryChart(result);
                updateMemoryDetailsChart(result);
            }

            @Override
            public void onFailure(Throwable caught) {
                Log.error("error while getting server memory stats:" + caught.getMessage());
            };
        });
    }

    private void updateRuntimeInfo(RuntimeInfo rti) {
        FlexTable ft = new FlexTable();
        ft.getElement().setId("infoTable");
        ft.setCellPadding(0);
        ft.setCellSpacing(0);
        ft.setText(0, 0, "Name/Value");
        ft.setText(0, 1, "Value");

        int i = 1;
        ft.setText(i++, 0, "Name");
        ft.setText(i++, 0, "BootClassPath");
        ft.setText(i++, 0, "ClassPath");
        ft.setText(i++, 0, "LibraryPath");
        ft.setText(i++, 0, "AvailableProcessors");
        ft.setText(i++, 0, "SystemLoadAverage");
        ft.setText(i++, 0, "InputArguments");
        ft.setText(i++, 0, "SystemProperties");

        ft.getRowFormatter().getElement(0).setId("th");

        i = 1;
        ft.setText(i++, 1, rti.getName());
        createWrappedHTML(ft, i++, rti.getBootClassPath());
        createWrappedHTML(ft, i++, rti.getClassPath());
        createWrappedHTML(ft, i++, rti.getLibraryPath());

        ft.setText(i++, 1, "" + rti.getAvailableProcessors());
        ft.setText(i++, 1, "" + rti.getSystemLoadAverage());

        TextArea ta = new TextArea();
        StringBuilder sb = new StringBuilder();
        for (String p : rti.getInputArguments()) {
            sb.append(p).append("\n");
        }
        ta.setText(sb.toString());
        ta.setSize("700px", "300px");
        ft.setWidget(i++, 1, ta);

        ta = new TextArea();
        sb = new StringBuilder();
        for (String key : rti.getSystemProperties().keySet()) {
            sb.append(key + " = " + rti.getSystemProperties().get(key)).append("\n");
        }
        ta.setText(sb.toString());
        ta.setSize("700px", "300px");
        ft.setWidget(i++, 1, ta);

        details.add(ft);
    }

    private void createWrappedHTML(FlexTable ft, int index, String text) {
        Widget h = getWrappedHtml(text);
        ft.setWidget(index, 1, h);
        ft.getCellFormatter().getElement(index, 1).setId("wrapContent");

    }

    private Widget getWrappedHtml(String text) {
        TextArea ta = new TextArea();
        ta.setText(text);
        ta.setSize("700px", "100px");
        return ta;
    }

    private void updateCpuChart(LinkedList<CpuUtilizationChunk> percentList) {
        ChartFeed<Double, Long> cpuHistory = new ChartFeed<Double, Long>(new Double[1][percentList.size()],
                new Long[percentList.size()]);
        for (int k = 0; k < 2; k++) {
            for (int j = 0; j < percentList.size(); j++) {
                if (k == 0) {
                    cpuHistory.getValues()[k][j] = percentList.get(j).getUsage();
                } else if (k == 1) {
                    cpuHistory.getXLineValues()[j] = percentList.get(j).getEndTime();
                }
            }
        }

        Log.debug("ServerStatsPopup.Updating CPU, values size:" + cpuHistory.getValuesLenght());
        cpuChart.updateChart(cpuHistory, true);
    }

    private void updateSysLoadChart(LinkedList<CpuUtilizationChunk> percentList) {
        ChartFeed<Double, Long> sysLoadFeed = new ChartFeed<Double, Long>(new Double[1][percentList.size()],
                new Long[percentList.size()]);
        for (int k = 0; k < 2; k++) {
            for (int j = 0; j < percentList.size(); j++) {
                if (k == 0) {
                    sysLoadFeed.getValues()[k][j] = percentList.get(j).getSystemLoadAverage();
                } else if (k == 1) {
                    sysLoadFeed.getXLineValues()[j] = percentList.get(j).getEndTime();
                }
            }
        }

        Log.debug("ServerStatsPopup.Updating SysLoad, values size:" + sysLoadFeed.getValuesLenght());
        sysLoadChart.updateChart(sysLoadFeed, true);
    }

    private void updateMemoryChart(LinkedList<MemoryUsage> result) {

        if (result == null) {
            Log.warn("Empty result in memmory stats");
            return;
        }

        ChartFeed<Double, Long> memoryHistory = new ChartFeed<Double, Long>(new Double[1][result.size()],
                new Long[result.size()]);
        for (int k = 0; k < 2; k++) {
            for (int j = 0; j < result.size(); j++) {
                if (k == 0) {
                    memoryHistory.getValues()[k][j] = result.get(j).getPercentage();
                } else if (k == 1) {
                    memoryHistory.getXLineValues()[j] = result.get(j).getEndTime();
                }
            }
        }

        Log.debug("ServerStatsPopup.Updating memry, values size:" + memoryHistory.getValuesLenght());
        memoryChart.updateChart(memoryHistory, true);
    }

    private void updateMemoryDetailsChart(LinkedList<MemoryUsage> result) {

        if (result == null) {
            Log.warn("Empty result in memmory stats");
            return;
        }

        HashMap<String, DynamicLine> names = new HashMap<String, DynamicLine>(0);
        int i = 0;
        for (MemoryUsage mu : result) {
            for (MemoryState memoryState : mu.getMemoryState()) {
                if (memoryState.isHeap() == showHeap && !names.containsKey(memoryState.getName())) {
                    names.put(memoryState.getName(),
                            new DynamicLine(i, memoryState.getName(), Colors.colors[i], ColumnType.NUMBER));
                    i++;
                }
            }
        }

        ChartFeed<Long, Long> memoryDetailsHistory = new ChartFeed<Long, Long>(
                new Long[names.size()][result.size()], new Long[result.size()]);
        for (int j = 0; j < result.size(); j++) {
            LinkedList<MemoryState> memoryState = result.get(j).getMemoryState();
            for (MemoryState ms : memoryState) {
                if (names.containsKey(ms.getName())) {
                    memoryDetailsHistory.getValues()[names.get(ms.getName()).getIndex()][j] = ms.getUsed();
                }
            }

            memoryDetailsHistory.getXLineValues()[j] = result.get(j).getEndTime();
        }

        Log.debug("ServerStatsPopup.Updating memry, values size:" + memoryDetailsHistory.getValuesLenght());

        List<ILineType> ilt = new ArrayList<ILineType>(names.values());
        memoryDetailsChart.updateChart(ilt, memoryDetailsHistory, true);
    }

    public Integer getServerCode() {
        return serverCode;
    }

}