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

Java tutorial

Introduction

Here is the source code for org.clevermore.monitor.client.servers.ServersWidget.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.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.clevermore.monitor.client.ServerWidgetService;
import org.clevermore.monitor.client.ServerWidgetServiceAsync;
import org.clevermore.monitor.client.utils.ClientStringFormatter;
import org.clevermore.monitor.client.utils.LocalStorage;
import org.clevermore.monitor.client.widgets.AbstractMonitoringWidget;
import org.clevermore.monitor.client.widgets.IMonitoringWidget;
import org.clevermore.monitor.shared.certificate.Certificate;
import org.clevermore.monitor.shared.config.ClientConfigurations;
import org.clevermore.monitor.shared.servers.ConnectedDB;
import org.clevermore.monitor.shared.servers.ConnectedServer;
import org.clevermore.monitor.shared.servers.ServersRefreshRequest;
import org.clevermore.monitor.shared.servers.ServersRefreshResponse;

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.Style;
import com.google.gwt.dom.client.Style.Cursor;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.Window;
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.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class ServersWidget<CC extends ClientConfigurations>
        extends AbstractMonitoringWidget<ServersRefreshRequest, ServersRefreshResponse, ServerWidgetServiceAsync>
        implements IMonitoringWidget {

    private static final String SERVERS_SHOW_OFF = "servers.showOff";
    private static final String SERVERS_FILTER = "servers.filter";

    private FlowPanel serversList = new FlowPanel();
    private ScrollPanel sp = new ScrollPanel();
    private boolean showOffline = true;
    private Button certs = new Button("Certificates");

    private ClickHandler getThreadDump = new ClickHandler() {

        @Override
        public void onClick(ClickEvent event) {
            String code = ((Widget) event.getSource()).getElement().getAttribute("code");
            if (code != null) {
                ServerStatsPopup<CC> ssp = new ServerStatsPopup<CC>(Integer.valueOf(code));
                ssp.center();
            } else {
                Window.alert("Server couldn't be found:" + code);
            }

        }
    };

    private ClickHandler getGCHistory = new ClickHandler() {

        @Override
        public void onClick(ClickEvent event) {
            String code = ((Widget) event.getSource()).getElement().getAttribute("code");
            getService().getGCHistory(Integer.valueOf(code), new AsyncCallback<String>() {

                @Override
                public void onSuccess(String result) {
                    GcHistoryPopup ghp = new GcHistoryPopup();
                    ghp.setText(result);
                    ghp.center();
                }

                @Override
                public void onFailure(Throwable caught) {
                    Window.alert("Can't get GC history:" + caught.getMessage());
                }
            });
        }
    };

    private MouseOverHandler handCursor = new MouseOverHandler() {

        @Override
        public void onMouseOver(MouseOverEvent event) {
            ((Widget) event.getSource()).getElement().getStyle().setCursor(Cursor.POINTER);
        }
    };

    private Map<Integer, ConnectedServer> serversMap = new HashMap<Integer, ConnectedServer>(0);
    private ArrayList<ConnectedServer> servesList;
    private ArrayList<ConnectedDB> databases;

    private HorizontalPanel title = new HorizontalPanel();
    private TextBox filter = new TextBox();
    private Label serversLabel = new Label("Servers");

    public ServersWidget() {
        super("Servers", 20000, (ServerWidgetServiceAsync) GWT.create(ServerWidgetService.class));

        addStyleName("serversWidget");
        serversList.setStyleName("serversWidgetInternal");
        getDataPanel().add(serversList);
        sp.setSize("100%", "100%");
        serversList.add(sp);

        title.setStyleName("serversHeader");
        setTitleWidget(title);
        title.add(serversLabel);
        final CheckBox chkShowOffline = new CheckBox("Show Offline");
        chkShowOffline.setValue(true);
        title.add(chkShowOffline);
        title.add(new Label("Filter:"));
        title.add(filter);

        Style style = certs.getElement().getStyle();
        style.setPadding(0, Unit.PX);
        title.add(certs);
        title.add(getRefProg());

        certs.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                getService().getCertificates(new AsyncCallback<HashMap<String, List<Certificate>>>() {

                    @Override
                    public void onSuccess(HashMap<String, List<Certificate>> result) {
                        new CertificatesPopup(result);
                    }

                    @Override
                    public void onFailure(Throwable caught) {
                        Window.alert(caught.getMessage());
                    }
                });
            }
        });

        String filterText = LocalStorage.readStoredItem(SERVERS_FILTER);
        if (filterText != null) {
            filter.setText(filterText.trim().toLowerCase());
        }

        filter.addKeyPressHandler(new KeyPressHandler() {

            @Override
            public void onKeyPress(KeyPressEvent event) {
                Log.debug("Key:" + event.getNativeEvent().getKeyCode());
                if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
                    updateServersTable();
                }
            }
        });

        String showOff = LocalStorage.readStoredItem(SERVERS_SHOW_OFF);
        if (showOff != null && (showOff.equals("1") || showOff.equals("0"))) {
            chkShowOffline.setValue(showOff.equals("1"));
            showOffline = showOff.equals("1");
        }

        chkShowOffline.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                showOffline = chkShowOffline.getValue();
                LocalStorage.storeItem(SERVERS_SHOW_OFF, showOffline ? "1" : "0");
            }
        });

    }

    @Override
    public void clear() {

    }

    private void updateServersTable() {
        sp.clear();
        FlexTable ft = new FlexTable();
        sp.add(ft);
        ft.getElement().setId("infoTable");
        ft.setCellPadding(0);
        ft.setCellSpacing(0);

        Collections.sort(servesList, new Comparator<ConnectedServer>() {

            @Override
            public int compare(ConnectedServer o1, ConnectedServer o2) {
                double o1p = 0, o2p = 0;
                if (o1.getStatus() && o2.getStatus()) {
                    if (o1.getCpuUsage() > 80 || o2.getCpuUsage() > 80) {
                        // sort by CPU
                        o1p = o1.getCpuUsage();
                        o2p = o2.getCpuUsage();
                    } else {
                        // sort by memory
                        o1p = o1.getMemoryUsage().getPercentage();
                        o2p = o2.getMemoryUsage().getPercentage();
                    }
                } else if (o1.getStatus()) {
                    o1p = o1.getMemoryUsage().getPercentage();
                    o2p = 100;
                } else if (o2.getStatus()) {
                    o1p = 100;
                    o2p = o2.getMemoryUsage().getPercentage();
                }
                return (int) (o2p * 100d - o1p * 100d);
            }
        });

        int i = 0, j = 0;
        HTML t;
        ft.setText(i, j++, "Code, Name");
        ft.setText(i, j++, "Up Time");

        t = new HTML("Memory");
        t.setTitle("Latest memory status.");
        ft.setWidget(i, j++, t);

        t = new HTML("Max GC");
        t.setTitle("Max GC time in the last 24 hours.");
        ft.setWidget(i, j++, t);

        t = new HTML("Cpu");
        t.setTitle("Latest CPU load.");
        ft.setWidget(i, j++, t);

        t = new HTML("SYSL");
        t.setTitle("Linux system load.");
        ft.setWidget(i, j++, t);

        ft.getRowFormatter().getElement(i++).setId("th");

        int offline = 0;

        serversMap.clear();

        for (ConnectedServer cs : servesList) {
            serversMap.put(cs.getServerCode(), cs);

            j = 0;
            offline += cs.getStatus() ? 0 : 1;
            if (!toShow(cs.getName())) {
                continue;
            }
            if (cs.getStatus()) {
                final HTML name = new HTML("<a href=#>" + cs.getServerCode() + "," + cs.getName() + "</a>");
                name.getElement().setAttribute("code", "" + cs.getServerCode());
                name.setTitle(cs.getToolTip());
                name.addMouseOverHandler(handCursor);

                name.addClickHandler(getThreadDump);

                ft.setWidget(i, j++, name);
                ft.setText(i, j++, ClientStringFormatter.formatMilisecondsToHours(cs.getUpTime()));

                HTML usage = new HTML(ClientStringFormatter.formatMBytes(cs.getMemoryUsage().getUsed()) + " / "
                        + ClientStringFormatter.formatMBytes(cs.getMemoryUsage().getMax()) + " MB,  "
                        + ClientStringFormatter.formatMillisShort(cs.getMemoryUsage().getPercentage()) + "%");
                ft.setWidget(i, j++, usage);

                StringBuilder gcs = new StringBuilder();
                double gcMax = Double.MIN_VALUE;

                // Iterating over all available pools
                for (Double gch : cs.getGcHistories()) {
                    gcs.append(ClientStringFormatter.formatMillisShort(gch)).append(", ");
                    if (gch > gcMax) {
                        gcMax = gch;
                    }
                }
                if (gcs.length() > 0) {
                    gcs.setLength(gcs.length() - 2);
                }
                final HTML memory = new HTML(gcs.toString());
                memory.setTitle("Click to see GC history");
                memory.addMouseOverHandler(handCursor);
                memory.addClickHandler(getGCHistory);
                memory.getElement().setAttribute("code", "" + cs.getServerCode());

                ft.setWidget(i, j++, memory);
                if (gcMax > 3) {
                    Style style = ft.getFlexCellFormatter().getElement(i, j - 1).getStyle();
                    style.setBackgroundColor("#C00000");
                    style.setFontWeight(FontWeight.BOLDER);
                    style.setColor("white");
                }

                if (cs.getMemoryUsage().getPercentage() > 90) {
                    ft.getRowFormatter().getElement(i).setId("memoryVeryHigh");
                }
                // else if (cs.getMemoryUsage().getPercentage() > 80) {
                // ft.getRowFormatter().getElement(i).setId("memoryHigh");
                // }

                HTML cpu = new HTML(cs.getCpuUsage() + "%");
                ft.setWidget(i, j++, cpu);
                if (cs.getCpuUsage() > 90d) {
                    Style style = ft.getFlexCellFormatter().getElement(i, j - 1).getStyle();
                    style.setBackgroundColor("#C00000");
                    style.setFontWeight(FontWeight.BOLDER);
                    style.setColor("white");
                }

                double sla = cs.getSystemLoadAverage();
                HTML sysl = new HTML(sla == -1 ? "N/A" : ClientStringFormatter.formatMillisShort(sla));
                sysl.setTitle("System Load Average");
                ft.setWidget(i, j++, sysl);
                i++;

            } else {
                if (showOffline) {
                    final HTML name = new HTML("<a href=#>" + cs.getServerCode() + ", " + cs.getName() + "</a>");
                    name.setTitle("JMX >> " + cs.getIp() + ":" + cs.getJmxPort());
                    ft.setWidget(i, j++, name);
                    ft.setText(i, j++, "Offline");
                    ft.setText(i, j++, "Offline");
                    ft.setText(i, j++, "Offline");
                    ft.setText(i, j++, "0.0%");
                    ft.setText(i, j++, "0");
                    ft.getRowFormatter().getElement(i++).setId("offline");
                }
            }
        }

        ft.getColumnFormatter().setWidth(0, "100px");

        if (databases != null && databases.size() > 0) {
            for (ConnectedDB cd : databases) {
                j = 0;
                HTML value = new HTML("<b>Database</b>:" + cd.getName() + " (" + cd.getService() + ")");
                value.setTitle(cd.toString());
                ft.setWidget(i, j, value);
                ft.getFlexCellFormatter().setColSpan(i, j, 2);
                ft.setText(i, 1, cd.getIp() + ":" + cd.getPort());
                ft.setText(i, 2, (cd.getStatus() ? "ONLINE" : "OFFLINE"));
                ft.setText(i, 3, "LastPing:" + cd.getLastPingTime() + "ms");
                ft.getFlexCellFormatter().setColSpan(i, 3, 2);
                if ((!cd.getStatus())) {
                    ft.getRowFormatter().getElement(i).setId("offline");
                }
                i++;
            }
        }
        serversLabel.setText("Servers:" + servesList.size() + " (" + offline + ")");
    }

    private boolean toShow(String serverName) {
        filter.setText(filter.getText().trim().toLowerCase().replace(",", " "));
        if (filter.getText().length() > 0) {
            // filter
            LocalStorage.storeItem(SERVERS_FILTER, filter.getText());
            filter.getElement().getStyle().setBackgroundColor("#66FF00");

            String[] fil = filter.getText().split(" ");
            for (String f : fil) {
                if (f.trim().length() > 0 && serverName.trim().toLowerCase().contains(f)) {
                    return true;
                }
            }

            return false;

        } else {
            filter.getElement().getStyle().setBackgroundColor("white");
            LocalStorage.removeItem(SERVERS_FILTER);

            return true;
        }
    }

    @Override
    public ServersRefreshRequest createRefreshRequest() {
        return new ServersRefreshRequest();
    }

    @Override
    public void refreshFailed(Throwable t) {
        Log.error("ServerWidget, error refereshing:" + t.getMessage(), t);

    }

    @Override
    public void refresh(ServersRefreshResponse refershResponse) {
        Log.debug("ServerWidget, refereshing:" + refershResponse.toString());
        Log.debug("ServersWidget spInterrupted:" + sp.getVerticalScrollPosition());
        servesList = refershResponse.getServers();
        databases = refershResponse.getDatabases();
        updateServersTable();
        getRefProg().progress();

        if (refershResponse.isCertificateAlert()) {
            blinkCertButton();
        } else {
            stopBlinkCertButton();
        }
    }

    private void blinkCertButton() {
        Boolean blink = Boolean.valueOf(certs.getElement().getAttribute("blink"));
        if (!blink) {
            certs.getElement().setAttribute("blink", "true");
            Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {

                @Override
                public boolean execute() {
                    Boolean blink = Boolean.valueOf(certs.getElement().getAttribute("blink"));
                    Style style = certs.getElement().getStyle();
                    if (blink) {
                        style.setColor("red".equals(style.getColor()) ? "green" : "red");
                        style.setFontWeight(FontWeight.BOLDER);
                    } else {
                        style.setColor("black");
                        style.setFontWeight(FontWeight.NORMAL);
                    }
                    return blink;
                }
            }, 1000);
        }
    }

    private void stopBlinkCertButton() {
        certs.getElement().setAttribute("blink", "false");
    }

}