Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

removed gwt ui sources from project

  • Loading branch information...
commit 01cd1dcb38cd0518bf81cf888e7192040a540ad6 1 parent 814e54a
@bsjaekel authored
View
9 src/main/java/net/opentsdb/tsd/QueryUi.gwt.xml
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module rename-to="queryui">
- <inherits name="com.google.gwt.user.User"/>
- <inherits name="com.google.gwt.user.theme.standard.Standard"/>
- <inherits name="com.google.gwt.http.HTTP"/>
- <inherits name="com.google.gwt.json.JSON"/>
- <entry-point class="tsd.client.QueryUi"/>
- <source path="client"/>
-</module>
View
357 src/main/java/net/opentsdb/tsd/client/DateTimeBox.java
@@ -1,357 +0,0 @@
-// This file is part of OpenTSDB.
-// Copyright (C) 2010-2012 The OpenTSDB Authors.
-//
-// This program is free software: you can redistribute it and/or modify it
-// under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 2.1 of the License, or (at your
-// option) any later version. This program is distributed in the hope that it
-// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details. You should have received a copy
-// of the GNU Lesser General Public License along with this program. If not,
-// see <http://www.gnu.org/licenses/>.
-package tsd.client;
-
-import java.util.Date;
-
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DomEvent;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.InlineHTML;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.PushButton;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.datepicker.client.DateBox;
-import com.google.gwt.user.datepicker.client.DatePicker;
-
-/**
- * A {@link DateBox} with support for time.
- * <p>
- * This class is unnecessarily complicated because {@link DateBox} wasn't
- * designed in an extensible way (semi-purposefully). A thread gwt-contrib
- * titled "DatePicker DatePickerComponent protected ?" from 2008 shows that
- * back then they were working on an extensible {@link DateBox} and
- * {@link DatePicker} for GWT 2, but as of Sep 2010 this hasn't happened.
- * Their suggestion to copy-paste-hack the code is unacceptable so instead
- * we go through a few hoops to make this work.
- */
-final class DateTimeBox extends DateBox {
-
- private static final DateTimeFormat HHMM_FORMAT =
- DateTimeFormat.getFormat("HH:mm");
-
- private static final DefaultFormat DATE_FORMAT =
- new DefaultFormat(DateTimeFormat.getFormat("yyyy/MM/dd-HH:mm:ss")) {
- /** Adds support for some human readable dates ("1d ago", "10:30"). */
- @Override
- public Date parse(final DateBox box,
- final String text,
- final boolean report_error) {
- if (text.endsWith(" ago") || text.endsWith("-ago")) { // e.g. "1d ago".
- int interval;
- final int lastchar = text.length() - 5;
- try {
- interval = Integer.parseInt(text.substring(0, lastchar));
- } catch (NumberFormatException e) {
- setError(box);
- return null;
- }
- if (interval <= 0) {
- setError(box);
- return null;
- }
- switch (text.charAt(lastchar)) {
- case 's': break; // seconds
- case 'm': interval *= 60; break; // minutes
- case 'h': interval *= 3600; break; // hours
- case 'd': interval *= 3600 * 24; break; // days
- case 'w': interval *= 3600 * 24 * 7; break; // weeks
- case 'y': interval *= 3600 * 24 * 365; break; // years
- }
- final Date d = new Date();
- d.setTime(d.getTime() - interval * 1000L);
- return d;
- } else if (text.length() == 5) { // "HH:MM"
- try {
- return HHMM_FORMAT.parse(text);
- } catch (IllegalArgumentException ignored) {
- setError(box);
- return null;
- }
- }
- return super.parse(box, text, report_error);
- }
-
- private void setError(final DateBox box) {
- box.addStyleName("dateBoxFormatError");
- }
- };
-
- public DateTimeBox() {
- super(new DateTimePicker(), null, DATE_FORMAT);
- ((DateTimePicker) getDatePicker()).setDateTimeBox(this);
- final TextBox textbox = getTextBox();
- // Chrome 7.0.5xx versions, Safari 5.0.x and similar render a text box
- // that's too small for 19 characters (WTF?). So we ask for space for
- // an extra 2 characters. On Firefox the text box's width is computed
- // properly, so it simply appears slightly wider than necessary.
- textbox.setVisibleLength(19 + 2);
- textbox.setMaxLength(19);
- }
-
- /**
- * A {@link DatePicker} with a customized UI for time support.
- */
- private static final class DateTimePicker extends DatePicker {
-
- /** DateTimeBox this picker belongs to. */
- private DateTimeBox box;
- /** A grid in which we put some buttons we may need to update. */
- private Grid hours_minutes;
-
- public DateTimePicker() {
- }
-
- /**
- * Sets the {@link DateTimeBox} this {@link DateTimePicker} belongs to.
- * This <b>must</b> be called before using this object.
- */
- void setDateTimeBox(final DateTimeBox box) {
- this.box = box;
- }
-
- /**
- * Sets the date of the {@link DateBox} to the given {@link Date}.
- */
- private void setDate(final Date d) {
- refreshAll();
- box.setValue(d);
- // Put the focus back on the text box to make it easier for the
- // user to manually edit the field.
- box.getTextBox().setFocus(true);
- }
-
- /**
- * Returns a new button that shifts the date when clicked.
- * @param seconds How many seconds to shift.
- * @param label The label to put on the button.
- */
- private PushButton newShiftDateButton(final int seconds,
- final String label) {
- final PushButton button = new PushButton(label);
- button.setStyleName(seconds < 0 ? "datePickerPreviousButton"
- : "datePickerNextButton");
- button.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- Date d = box.getValue();
- if (d == null) {
- if (seconds >= 0) {
- return;
- }
- d = new Date();
- }
- d.setTime(d.getTime() + seconds * 1000L);
- d.setSeconds(0);
- setDate(d);
- }
- });
- return button;
- }
-
- /**
- * Returns a new button that sets the hours when clicked.
- * @param hours An hour of the day (0-23).
- * @param label The label to put on the button.
- */
- private PushButton newSetHoursButton(final int hours) {
- final PushButton button = new PushButton(Integer.toString(hours));
- button.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- @SuppressWarnings(/* GWT requires us to use Date */{"deprecation"})
- Date d = box.getValue();
- if (d == null) {
- d = new Date();
- d.setMinutes(0);
- }
- d.setHours(hours);
- d.setSeconds(0);
- setDate(d);
- }
- });
- return button;
- }
-
- /**
- * Returns a new button that sets the minutes when clicked.
- * @param minutes A value for minutes (0-59).
- * @param label The label to put on the button.
- */
- private PushButton newSetMinutesButton(final int minutes,
- final String label) {
- final PushButton button = new PushButton(label);
- button.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- @SuppressWarnings(/* GWT requires us to use Date */{"deprecation"})
- Date d = box.getValue();
- if (d == null) {
- d = new Date();
- }
- d.setMinutes(minutes);
- d.setSeconds(0);
- setDate(d);
- }
- });
- return button;
- }
-
- /** Rebuilds parts of the UI with buttons to set AM hours. */
- private void setupAmUI() {
- hours_minutes.setWidget(0, 1, newSetHoursButton(0));
- hours_minutes.setWidget(0, 2, newSetHoursButton(1));
- hours_minutes.setWidget(0, 3, newSetHoursButton(2));
- hours_minutes.setWidget(0, 4, newSetHoursButton(3));
- hours_minutes.setWidget(0, 5, newSetHoursButton(4));
- hours_minutes.setWidget(0, 6, newSetHoursButton(5));
- hours_minutes.setWidget(1, 1, newSetHoursButton(6));
- hours_minutes.setWidget(1, 2, newSetHoursButton(7));
- hours_minutes.setWidget(1, 3, newSetHoursButton(8));
- hours_minutes.setWidget(1, 4, newSetHoursButton(9));
- hours_minutes.setWidget(1, 5, newSetHoursButton(10));
- hours_minutes.setWidget(1, 6, newSetHoursButton(11));
- }
-
- /** Rebuilds parts of the UI with buttons to set PM hours. */
- private void setupPmUI() {
- hours_minutes.setWidget(0, 1, newSetHoursButton(12));
- hours_minutes.setWidget(0, 2, newSetHoursButton(13));
- hours_minutes.setWidget(0, 3, newSetHoursButton(14));
- hours_minutes.setWidget(0, 4, newSetHoursButton(15));
- hours_minutes.setWidget(0, 5, newSetHoursButton(16));
- hours_minutes.setWidget(0, 6, newSetHoursButton(17));
- hours_minutes.setWidget(1, 1, newSetHoursButton(18));
- hours_minutes.setWidget(1, 2, newSetHoursButton(19));
- hours_minutes.setWidget(1, 3, newSetHoursButton(20));
- hours_minutes.setWidget(1, 4, newSetHoursButton(21));
- hours_minutes.setWidget(1, 5, newSetHoursButton(22));
- hours_minutes.setWidget(1, 6, newSetHoursButton(23));
- }
-
- /** Sets up the custom UI of the date picker. */
- @Override
- protected void setup() {
- final HorizontalPanel panel = new HorizontalPanel();
- initWidget(panel);
- setStyleName(panel.getElement(), "gwt-DatePicker");
-
- {
- final VerticalPanel vbox = new VerticalPanel();
- setStyleName("gwt-DatePicker");
- vbox.add(super.getMonthSelector());
- vbox.add(super.getView());
-
- panel.add(vbox);
- }
-
- {
- // This vbox contains all of the "extra" panel on the side
- // of the calendar view.
- final VerticalPanel vbox = new VerticalPanel();
- setStyleName(vbox.getElement(), "datePickerMonthSelector");
-
- final PushButton now = new PushButton("now");
- now.setStyleName("datePickerNextButton");
- now.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- box.setValue(new Date());
- }
- });
-
- {
- final Grid grid = new Grid(2, 9);
- grid.setWidget(0, 0, newShiftDateButton(-3600, "1h"));
- grid.setWidget(0, 1, newShiftDateButton(-600, "10m"));
- grid.setWidget(0, 2, newShiftDateButton(-60, "1m"));
- grid.setWidget(0, 3, new InlineHTML("&lsaquo;"));
- grid.setWidget(0, 4, now);
- grid.setWidget(0, 5, new InlineHTML("&rsaquo;"));
- grid.setWidget(0, 6, newShiftDateButton(+60, "1m"));
- grid.setWidget(0, 7, newShiftDateButton(+600, "10m"));
- grid.setWidget(0, 8, newShiftDateButton(+3600, "1h"));
- grid.setWidget(1, 0, newShiftDateButton(-86400 * 30, "30d"));
- grid.setWidget(1, 1, newShiftDateButton(-86400 * 7, "1w"));
- grid.setWidget(1, 2, newShiftDateButton(-86400, "1d"));
- grid.setWidget(1, 3, new InlineHTML("&laquo;"));
- grid.setWidget(1, 4, new InlineHTML("&nbsp;"));
- grid.setWidget(1, 5, new InlineHTML("&raquo;"));
- grid.setWidget(1, 6, newShiftDateButton(+86400, "1d"));
- grid.setWidget(1, 7, newShiftDateButton(+86400 * 7, "1w"));
- grid.setWidget(1, 8, newShiftDateButton(+86400 * 30, "30d"));
- final CellFormatter formatter = grid.getCellFormatter();
- formatter.setWidth(0, 4, "100%");
- formatter.setWidth(1, 4, "100%");
- vbox.add(grid);
- }
-
- {
- hours_minutes = new Grid(4, 8);
- setupAmUI();
- hours_minutes.setWidget(0, 0, new InlineLabel("HH"));
- final PushButton set_am = new PushButton("AM");
- set_am.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- setupAmUI();
- }
- });
- hours_minutes.setWidget(0, 7, set_am);
-
- final PushButton set_pm = new PushButton("PM");
- set_pm.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- setupPmUI();
- }
- });
- hours_minutes.setWidget(1, 7, set_pm);
-
- hours_minutes.setWidget(2, 0, new InlineLabel("MM"));
- hours_minutes.setWidget(2, 1, newSetMinutesButton(0, "00"));
- hours_minutes.setWidget(2, 2, newSetMinutesButton(10, "10"));
- hours_minutes.setWidget(2, 3, newSetMinutesButton(20, "20"));
- hours_minutes.setWidget(2, 4, newSetMinutesButton(30, "30"));
- hours_minutes.setWidget(2, 5, newSetMinutesButton(40, "40"));
- hours_minutes.setWidget(2, 6, newSetMinutesButton(50, "50"));
- vbox.add(hours_minutes);
- }
-
- {
- final HorizontalPanel hbox = new HorizontalPanel();
- hbox.add(new InlineLabel("UNIX timestamp:"));
- final ValidatedTextBox ts = new ValidatedTextBox();
- ts.setValidationRegexp("^(|[1-9][0-9]{0,9})$");
- ts.setVisibleLength(10);
- ts.setMaxLength(10);
- final EventsHandler handler = new EventsHandler() {
- protected <H extends EventHandler> void onEvent(final DomEvent<H> event) {
- final Date d = new Date(Integer.parseInt(ts.getValue()) * 1000L);
- box.setValue(d, true);
- }
- };
- ts.addBlurHandler(handler);
- ts.addKeyPressHandler(handler);
- hbox.add(ts);
- vbox.add(hbox);
- }
- vbox.setHeight("100%");
- panel.add(vbox);
- panel.setCellHeight(vbox, "100%");
- }
- }
-
- }
-
-}
View
81 src/main/java/net/opentsdb/tsd/client/EventsHandler.java
@@ -1,81 +0,0 @@
-// This file is part of OpenTSDB.
-// Copyright (C) 2010-2012 The OpenTSDB Authors.
-//
-// This program is free software: you can redistribute it and/or modify it
-// under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 2.1 of the License, or (at your
-// option) any later version. This program is distributed in the hope that it
-// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details. You should have received a copy
-// of the GNU Lesser General Public License along with this program. If not,
-// see <http://www.gnu.org/licenses/>.
-package tsd.client;
-
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ChangeEvent;
-import com.google.gwt.event.dom.client.ChangeHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DomEvent;
-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.shared.EventHandler;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DeferredCommand;
-
-/**
- * Handler for multiple events that indicate that the widget may have changed.
- * <p>
- * This handler is just a convenient 4-in-1 handler that can be re-used on a
- * wide range of widgets such as {@code TextBox} and its derivative,
- * {@code CheckBox}, {@code ListBox} etc.
- */
-abstract class EventsHandler implements BlurHandler, ChangeHandler,
- ClickHandler, KeyPressHandler {
-
- /**
- * Called <em>after</em> one of the events (click, blur, change or "enter"
- * is pressed) occurs.
- * <p>
- * This method is NOT called while the event is happening. It's invoked via
- * a {@link DeferredCommand deferred command}. This entails that the event
- * can't be cancelled as it has already executed. The reason the call is
- * deferred is that this way, things like {@code SuggestBox}s will have
- * already done their auto-completion by the time this method is called, and
- * thus the handler will see the suggested text instead of the partial input
- * being typed by the user.
- * @param event The event that occurred.
- */
- protected abstract <H extends EventHandler> void onEvent(DomEvent<H> event);
-
- public final void onClick(final ClickEvent event) {
- scheduleEvent(event);
- }
-
- public final void onBlur(final BlurEvent event) {
- scheduleEvent(event);
- }
-
- public final void onChange(final ChangeEvent event) {
- scheduleEvent(event);
- }
-
- public final void onKeyPress(final KeyPressEvent event) {
- if (event.getCharCode() == KeyCodes.KEY_ENTER) {
- scheduleEvent(event);
- }
- }
-
- /** Executes the event using a deferred command. */
- private <H extends EventHandler> void scheduleEvent(final DomEvent<H> event) {
- DeferredCommand.addCommand(new Command() {
- public void execute() {
- onEvent(event);
- }
- });
- }
-
-}
View
21 src/main/java/net/opentsdb/tsd/client/GotJsonCallback.java
@@ -1,21 +0,0 @@
-// This file is part of OpenTSDB.
-// Copyright (C) 2010-2012 The OpenTSDB Authors.
-//
-// This program is free software: you can redistribute it and/or modify it
-// under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 2.1 of the License, or (at your
-// option) any later version. This program is distributed in the hope that it
-// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details. You should have received a copy
-// of the GNU Lesser General Public License along with this program. If not,
-// see <http://www.gnu.org/licenses/>.
-package tsd.client;
-
-import com.google.gwt.json.client.JSONValue;
-
-interface GotJsonCallback {
-
- void got(JSONValue json);
-
-}
View
509 src/main/java/net/opentsdb/tsd/client/MetricForm.java
@@ -1,509 +0,0 @@
-// This file is part of OpenTSDB.
-// Copyright (C) 2010-2012 The OpenTSDB Authors.
-//
-// This program is free software: you can redistribute it and/or modify it
-// under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 2.1 of the License, or (at your
-// option) any later version. This program is distributed in the hope that it
-// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details. You should have received a copy
-// of the GNU Lesser General Public License along with this program. If not,
-// see <http://www.gnu.org/licenses/>.
-package tsd.client;
-
-import java.util.ArrayList;
-
-import com.google.gwt.event.dom.client.BlurEvent;
-import com.google.gwt.event.dom.client.BlurHandler;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DomEvent;
-import com.google.gwt.event.shared.EventHandler;
-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.Focusable;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.ListBox;
-import com.google.gwt.user.client.ui.SuggestBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-final class MetricForm extends HorizontalPanel implements Focusable {
-
- public static interface MetricChangeHandler extends EventHandler {
- void onMetricChange(MetricForm widget);
- }
-
- private static final String TSDB_ID_CLASS = "[-_./a-zA-Z0-9]";
- private static final String TSDB_ID_RE = "^" + TSDB_ID_CLASS + "*$";
- private static final String TSDB_TAGVALUE_RE =
- "^(\\*?" // a `*' wildcard or nothing
- + "|" + TSDB_ID_CLASS + "+(\\|" + TSDB_ID_CLASS + "+)*)$"; // `foo|bar|...'
-
- private final EventsHandler events_handler;
- private MetricChangeHandler metric_change_handler;
-
- private final CheckBox downsample = new CheckBox("Downsample");
- private final ListBox downsampler = new ListBox();
- private final ValidatedTextBox interval = new ValidatedTextBox();
- private final CheckBox rate = new CheckBox("Rate");
- private final CheckBox x1y2 = new CheckBox("Right Axis");
- private final ListBox aggregators = new ListBox();
- private final ValidatedTextBox metric = new ValidatedTextBox();
- private final FlexTable tagtable = new FlexTable();
-
- public MetricForm(final EventsHandler handler) {
- events_handler = handler;
- setupDownsampleWidgets();
- downsample.addClickHandler(handler);
- downsampler.addChangeHandler(handler);
- interval.addBlurHandler(handler);
- interval.addKeyPressHandler(handler);
- rate.addClickHandler(handler);
- x1y2.addClickHandler(handler);
- aggregators.addChangeHandler(handler);
- metric.addBlurHandler(handler);
- metric.addKeyPressHandler(handler);
- {
- final EventsHandler metric_handler = new EventsHandler() {
- protected <H extends EventHandler> void onEvent(final DomEvent<H> event) {
- if (metric_change_handler != null) {
- metric_change_handler.onMetricChange(MetricForm.this);
- }
- }
- };
- metric.addBlurHandler(metric_handler);
- metric.addKeyPressHandler(metric_handler);
- }
-
- metric.setValidationRegexp(TSDB_ID_RE);
- assembleUi();
- }
-
- public String getMetric() {
- return metric.getText();
- }
-
- /**
- * Parses the metric and tags out of the given string.
- * @param metric A string of the form "metric" or "metric{tag=value,...}".
- * @return The name of the metric.
- */
- private String parseWithMetric(final String metric) {
- // TODO: Try to reduce code duplication with Tags.parseWithMetric().
- final int curly = metric.indexOf('{');
- if (curly < 0) {
- clearTags();
- return metric;
- }
- final int len = metric.length();
- if (metric.charAt(len - 1) != '}') { // "foo{"
- clearTags();
- return null; // Missing '}' at the end.
- } else if (curly == len - 2) { // "foo{}"
- clearTags();
- return metric.substring(0, len - 2);
- }
- // substring the tags out of "foo{a=b,...,x=y}" and parse them.
- int i = 0; // Tag index.
- final int num_tags_before = getNumTags();
- for (final String tag : metric.substring(curly + 1, len - 1).split(",")) {
- final String[] kv = tag.split("=");
- if (kv.length != 2 || kv[0].isEmpty() || kv[1].isEmpty()) {
- setTag(i, "", "");
- continue; // Invalid tag.
- }
- if (i < num_tags_before) {
- setTag(i, kv[0], kv[1]);
- } else {
- addTag(kv[0], kv[1]);
- }
- i++;
- }
- // Leave an empty line at the end.
- if (i < num_tags_before) {
- setTag(i, "", "");
- } else {
- addTag();
- }
- // Remove extra tags.
- for (i++; i < num_tags_before; i++) {
- tagtable.removeRow(i + 1);
- }
- // Return the "foo" part of "foo{a=b,...,x=y}"
- return metric.substring(0, curly);
- }
-
- public void updateFromQueryString(final String m, final String o) {
- // TODO: Try to reduce code duplication with GraphHandler.parseQuery().
- // m is of the following forms:
- // agg:[interval-agg:][rate:]metric[{tag=value,...}]
- // Where the parts in square brackets `[' .. `]' are optional.
- final String[] parts = m.split(":");
- final int nparts = parts.length;
- int i = parts.length;
- if (i < 2 || i > 4) {
- return; // Malformed.
- }
-
- setSelectedItem(aggregators, parts[0]);
-
- i--; // Move to the last part (the metric name).
- metric.setText(parseWithMetric(parts[i]));
- metric_change_handler.onMetricChange(this);
-
- final boolean rate = "rate".equals(parts[--i]);
- this.rate.setValue(rate, false);
- if (rate) {
- i--;
- }
-
- // downsampling function & interval.
- if (i > 0) {
- final int dash = parts[1].indexOf('-', 1); // 1st char can't be `-'.
- if (dash < 0) {
- disableDownsample();
- return; // Invalid downsampling specifier.
- }
- downsample.setValue(true, false);
-
- downsampler.setEnabled(true);
- setSelectedItem(downsampler, parts[1].substring(dash + 1));
-
- interval.setEnabled(true);
- interval.setText(parts[1].substring(0, dash));
- } else {
- disableDownsample();
- }
-
- x1y2.setValue(o.contains("axis x1y2"), false);
- }
-
- private void disableDownsample() {
- downsample.setValue(false, false);
- interval.setEnabled(false);
- downsampler.setEnabled(false);
- }
-
- public CheckBox x1y2() {
- return x1y2;
- }
-
- private void assembleUi() {
- setWidth("100%");
- { // Left hand-side panel.
- final HorizontalPanel hbox = new HorizontalPanel();
- final InlineLabel l = new InlineLabel();
- l.setText("Metric:");
- hbox.add(l);
- final SuggestBox suggest = RemoteOracle.newSuggestBox("metrics",
- metric);
- suggest.setLimit(40);
- hbox.add(suggest);
- hbox.setWidth("100%");
- metric.setWidth("100%");
-
- tagtable.setWidget(0, 0, hbox);
- tagtable.getFlexCellFormatter().setColSpan(0, 0, 3);
- addTag();
- tagtable.setText(1, 0, "Tags");
- add(tagtable);
- }
- { // Right hand-side panel.
- final VerticalPanel vbox = new VerticalPanel();
- {
- final HorizontalPanel hbox = new HorizontalPanel();
- hbox.add(rate);
- hbox.add(x1y2);
- vbox.add(hbox);
- }
- {
- final HorizontalPanel hbox = new HorizontalPanel();
- final InlineLabel l = new InlineLabel();
- l.setText("Aggregator:");
- hbox.add(l);
- hbox.add(aggregators);
- vbox.add(hbox);
- }
- vbox.add(downsample);
- {
- final HorizontalPanel hbox = new HorizontalPanel();
- hbox.add(downsampler);
- hbox.add(interval);
- vbox.add(hbox);
- }
- add(vbox);
- }
- }
-
- public void setMetricChangeHandler(final MetricChangeHandler handler) {
- metric_change_handler = handler;
- }
-
- public void setAggregators(final ArrayList<String> aggs) {
- for (final String agg : aggs) {
- aggregators.addItem(agg);
- downsampler.addItem(agg);
- }
- setSelectedItem(aggregators, "sum");
- setSelectedItem(downsampler, "avg");
- }
-
- public boolean buildQueryString(final StringBuilder url) {
- final String metric = getMetric();
- if (metric.isEmpty()) {
- return false;
- }
- url.append("&m=");
- url.append(selectedValue(aggregators));
- if (downsample.getValue()) {
- url.append(':').append(interval.getValue())
- .append('-').append(selectedValue(downsampler));
- }
- if (rate.getValue()) {
- url.append(":rate");
- }
- url.append(':').append(metric);
- {
- final int ntags = getNumTags();
- url.append('{');
- for (int tag = 0; tag < ntags; tag++) {
- final String tagname = getTagName(tag);
- final String tagvalue = getTagValue(tag);
- if (tagname.isEmpty() || tagvalue.isEmpty()) {
- continue;
- }
- url.append(tagname).append('=').append(tagvalue)
- .append(',');
- }
- final int last = url.length() - 1;
- if (url.charAt(last) == '{') { // There was no tag.
- url.setLength(last); // So remove the `{'.
- } else { // Need to replace the last `,' with a `}'.
- url.setCharAt(url.length() - 1, '}');
- }
- }
- url.append("&o=");
- if (x1y2.getValue()) {
- url.append("axis x1y2");
- }
- return true;
- }
-
- private int getNumTags() {
- return tagtable.getRowCount() - 1;
- }
-
- private String getTagName(final int i) {
- return ((SuggestBox) tagtable.getWidget(i + 1, 1)).getValue();
- }
-
- private String getTagValue(final int i) {
- return ((SuggestBox) tagtable.getWidget(i + 1, 2)).getValue();
- }
-
- private void setTagName(final int i, final String value) {
- ((SuggestBox) tagtable.getWidget(i + 1, 1)).setValue(value);
- }
-
- private void setTagValue(final int i, final String value) {
- ((SuggestBox) tagtable.getWidget(i + 1, 2)).setValue(value);
- }
-
- /**
- * Changes the name/value of an existing tag.
- * @param i The index of the tag to change.
- * @param name The new name of the tag.
- * @param value The new value of the tag.
- * Requires: {@code i < getNumTags()}.
- */
- private void setTag(final int i, final String name, final String value) {
- setTagName(i, name);
- setTagValue(i, value);
- }
-
- private void addTag() {
- addTag(null, null);
- }
-
- private void addTag(final String default_tagname) {
- addTag(default_tagname, null);
- }
-
- private void addTag(final String default_tagname,
- final String default_value) {
- final int row = tagtable.getRowCount();
-
- final ValidatedTextBox tagname = new ValidatedTextBox();
- final SuggestBox suggesttagk = RemoteOracle.newSuggestBox("tagk", tagname);
- final ValidatedTextBox tagvalue = new ValidatedTextBox();
- final SuggestBox suggesttagv = RemoteOracle.newSuggestBox("tagv", tagvalue);
- tagname.setValidationRegexp(TSDB_ID_RE);
- tagvalue.setValidationRegexp(TSDB_TAGVALUE_RE);
- tagname.setWidth("100%");
- tagvalue.setWidth("100%");
- tagname.addBlurHandler(recompact_tagtable);
- tagname.addBlurHandler(events_handler);
- tagname.addKeyPressHandler(events_handler);
- tagvalue.addBlurHandler(recompact_tagtable);
- tagvalue.addBlurHandler(events_handler);
- tagvalue.addKeyPressHandler(events_handler);
-
- tagtable.setWidget(row, 1, suggesttagk);
- tagtable.setWidget(row, 2, suggesttagv);
- if (row > 2) {
- final Button remove = new Button("x");
- remove.addClickHandler(removetag);
- tagtable.setWidget(row - 1, 0, remove);
- }
- if (default_tagname != null) {
- tagname.setText(default_tagname);
- if (default_value == null) {
- tagvalue.setFocus(true);
- }
- }
- if (default_value != null) {
- tagvalue.setText(default_value);
- }
- }
-
- private void clearTags() {
- setTag(0, "", "");
- for (int i = getNumTags() - 1; i > 1; i++) {
- tagtable.removeRow(i + 1);
- }
- }
-
- public void autoSuggestTag(final String tag) {
- // First try to see if the tag is already in the table.
- final int nrows = tagtable.getRowCount();
- int unused_row = -1;
- for (int row = 1; row < nrows; row++) {
- final SuggestBox tagname = ((SuggestBox) tagtable.getWidget(row, 1));
- final SuggestBox tagvalue = ((SuggestBox) tagtable.getWidget(row, 2));
- final String thistag = tagname.getValue();
- if (thistag.equals(tag)) {
- return; // This tag is already in the table.
- } if (thistag.isEmpty() && tagvalue.getValue().isEmpty()) {
- unused_row = row;
- break;
- }
- }
- if (unused_row >= 0) {
- ((SuggestBox) tagtable.getWidget(unused_row, 1)).setValue(tag);
- } else {
- addTag(tag);
- }
- }
-
- private final BlurHandler recompact_tagtable = new BlurHandler() {
- public void onBlur(final BlurEvent event) {
- int ntags = getNumTags();
- // Is the first line empty? If yes, move everything up by 1 line.
- if (getTagName(0).isEmpty() && getTagValue(0).isEmpty()) {
- for (int tag = 1; tag < ntags; tag++) {
- final String tagname = getTagName(tag);
- final String tagvalue = getTagValue(tag);
- setTag(tag - 1, tagname, tagvalue);
- }
- setTag(ntags - 1, "", "");
- }
- // Try to remove empty lines from the tag table (but never remove the
- // first line or last line, even if they're empty). Walk the table
- // from the end to make it easier to delete rows as we iterate.
- for (int tag = ntags - 1; tag >= 1; tag--) {
- final String tagname = getTagName(tag);
- final String tagvalue = getTagValue(tag);
- if (tagname.isEmpty() && tagvalue.isEmpty()) {
- tagtable.removeRow(tag + 1);
- }
- }
- ntags = getNumTags(); // How many lines are left?
- // If the last line isn't empty, add another one.
- final String tagname = getTagName(ntags - 1);
- final String tagvalue = getTagValue(ntags - 1);
- if (!tagname.isEmpty() && !tagvalue.isEmpty()) {
- addTag();
- }
- }
- };
-
- private final ClickHandler removetag = new ClickHandler() {
- public void onClick(final ClickEvent event) {
- if (!(event.getSource() instanceof Button)) {
- return;
- }
- final Widget source = (Widget) event.getSource();
- final int ntags = getNumTags();
- for (int tag = 1; tag < ntags; tag++) {
- if (source == tagtable.getWidget(tag + 1, 0)) {
- tagtable.removeRow(tag + 1);
- events_handler.onClick(event);
- break;
- }
- }
- }
- };
-
- private void setupDownsampleWidgets() {
- downsampler.setEnabled(false);
- interval.setEnabled(false);
- interval.setMaxLength(5);
- interval.setVisibleLength(5);
- interval.setValue("10m");
- interval.setValidationRegexp("^[1-9][0-9]*[smhdwy]$");
- downsample.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- final boolean checked = ((CheckBox) event.getSource()).getValue();
- downsampler.setEnabled(checked);
- interval.setEnabled(checked);
- if (checked) {
- downsampler.setFocus(true);
- }
- }
- });
- }
-
- private static String selectedValue(final ListBox list) { // They should add
- return list.getValue(list.getSelectedIndex()); // this to GWT...
- }
-
- /**
- * If the given item is in the list, mark it as selected.
- * @param list The list to manipulate.
- * @param item The item to select if present.
- */
- private void setSelectedItem(final ListBox list, final String item) {
- final int nitems = list.getItemCount();
- for (int i = 0; i < nitems; i++) {
- if (item.equals(list.getValue(i))) {
- list.setSelectedIndex(i);
- return;
- }
- }
- }
-
- // ------------------- //
- // Focusable interface //
- // ------------------- //
-
- public int getTabIndex() {
- return metric.getTabIndex();
- }
-
- public void setTabIndex(final int index) {
- metric.setTabIndex(index);
- }
-
- public void setAccessKey(final char key) {
- metric.setAccessKey(key);
- }
-
- public void setFocus(final boolean focused) {
- metric.setFocus(focused);
- }
-
-}
View
92 src/main/java/net/opentsdb/tsd/client/QueryString.java
@@ -1,92 +0,0 @@
-// This file is part of OpenTSDB.
-// Copyright (C) 2012 The OpenTSDB Authors.
-//
-// This program is free software: you can redistribute it and/or modify it
-// under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 2.1 of the License, or (at your
-// option) any later version. This program is distributed in the hope that it
-// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details. You should have received a copy
-// of the GNU Lesser General Public License along with this program. If not,
-// see <http://www.gnu.org/licenses/>.
-package tsd.client;
-
-// I (tsuna) originally wrote this code for Netty. Surprisingly, GWT has
-// nothing to manually parse query string parameters...
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import com.google.gwt.http.client.URL;
-
-/**
- * Splits an HTTP query string into a path string and key-value parameter pairs.
- */
-public final class QueryString extends HashMap<String, ArrayList<String>> {
-
- /**
- * Returns the decoded key-value parameter pairs of the URI.
- */
- public static QueryString decode(final String s) {
- final QueryString params = new QueryString();
- String name = null;
- int pos = 0; // Beginning of the unprocessed region
- int i; // End of the unprocessed region
- for (i = 0; i < s.length(); i++) {
- final char c = s.charAt(i);
- if (c == '=' && name == null) {
- if (pos != i) {
- name = URL.decodeComponent(s.substring(pos, i));
- }
- pos = i + 1;
- } else if (c == '&') {
- if (name == null && pos != i) {
- // We haven't seen an `=' so far but moved forward.
- // Must be a param of the form '&a&' so add it with
- // an empty value.
- params.add(URL.decodeComponent(s.substring(pos, i)), "");
- } else if (name != null) {
- params.add(name, URL.decodeComponent(s.substring(pos, i)));
- name = null;
- }
- pos = i + 1;
- }
- }
-
- if (pos != i) { // Are there characters we haven't dealt with?
- if (name == null) { // Yes and we haven't seen any `='.
- params.add(URL.decodeComponent(s.substring(pos, i)), "");
- } else { // Yes and this must be the last value.
- params.add(name, URL.decodeComponent(s.substring(pos, i)));
- }
- } else if (name != null) { // Have we seen a name without value?
- params.add(name, "");
- }
-
- return params;
- }
-
- /**
- * Adds a query string element.
- * @param name The name of the element.
- * @param value The value of the element.
- */
- public void add(final String name, final String value) {
- ArrayList<String> values = super.get(name);
- if (values == null) {
- values = new ArrayList<String>(1); // Often there's only 1 value.
- super.put(name, values);
- }
- values.add(value);
- }
-
- /**
- * Returns the first value for the given key, or {@code null}.
- */
- public String getFirst(final String key) {
- final ArrayList<String> values = super.get(key);
- return values == null ? null : values.get(0);
- }
-
-}
View
1,317 src/main/java/net/opentsdb/tsd/client/QueryUi.java
@@ -1,1317 +0,0 @@
-// This file is part of OpenTSDB.
-// Copyright (C) 2010-2012 The OpenTSDB Authors.
-//
-// This program is free software: you can redistribute it and/or modify it
-// under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 2.1 of the License, or (at your
-// option) any later version. This program is distributed in the hope that it
-// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
-// General Public License for more details. You should have received a copy
-// of the GNU Lesser General Public License along with this program. If not,
-// see <http://www.gnu.org/licenses/>.
-package tsd.client;
-
-/*
- * DISCLAIMER
- * This my first GWT code ever, so it's most likely horribly wrong as I've had
- * virtually no exposure to the technology except through the tutorial. --tsuna
- */
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-
-import com.google.gwt.core.client.EntryPoint;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
-import com.google.gwt.event.dom.client.DomEvent;
-import com.google.gwt.event.dom.client.ErrorEvent;
-import com.google.gwt.event.dom.client.ErrorHandler;
-import com.google.gwt.event.dom.client.LoadEvent;
-import com.google.gwt.event.dom.client.LoadHandler;
-import com.google.gwt.event.dom.client.MouseDownEvent;
-import com.google.gwt.event.dom.client.MouseDownHandler;
-import com.google.gwt.event.dom.client.MouseEvent;
-import com.google.gwt.event.dom.client.MouseMoveEvent;
-import com.google.gwt.event.dom.client.MouseMoveHandler;
-import com.google.gwt.event.dom.client.MouseUpEvent;
-import com.google.gwt.event.dom.client.MouseUpHandler;
-import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
-import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
-import com.google.gwt.event.logical.shared.ValueChangeEvent;
-import com.google.gwt.event.logical.shared.ValueChangeHandler;
-import com.google.gwt.event.shared.EventHandler;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.http.client.Request;
-import com.google.gwt.http.client.RequestBuilder;
-import com.google.gwt.http.client.RequestCallback;
-import com.google.gwt.http.client.RequestException;
-import com.google.gwt.http.client.Response;
-import com.google.gwt.http.client.URL;
-import com.google.gwt.i18n.client.DateTimeFormat;
-import com.google.gwt.json.client.JSONArray;
-import com.google.gwt.json.client.JSONNumber;
-import com.google.gwt.json.client.JSONObject;
-import com.google.gwt.json.client.JSONParser;
-import com.google.gwt.json.client.JSONString;
-import com.google.gwt.json.client.JSONValue;
-import com.google.gwt.user.client.Element;
-import com.google.gwt.user.client.History;
-import com.google.gwt.user.client.HistoryListener;
-import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.Window;
-import com.google.gwt.user.client.ui.AbsolutePanel;
-import com.google.gwt.user.client.ui.Anchor;
-import com.google.gwt.user.client.ui.CheckBox;
-import com.google.gwt.user.client.ui.DecoratedTabPanel;
-import com.google.gwt.user.client.ui.DecoratorPanel;
-import com.google.gwt.user.client.ui.DisclosurePanel;
-import com.google.gwt.user.client.ui.FlexTable;
-import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTML;
-import com.google.gwt.user.client.ui.HorizontalPanel;
-import com.google.gwt.user.client.ui.Image;
-import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.RadioButton;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.TextBox;
-import com.google.gwt.user.client.ui.VerticalPanel;
-import com.google.gwt.user.client.ui.Widget;
-
-/**
- * Root class for the 'query UI'.
- * Manages the entire UI, forms to query the TSDB and other misc panels.
- */
-public class QueryUi implements EntryPoint, HistoryListener {
- // Some URLs we use to fetch data from the TSD.
- private static final String AGGREGATORS_URL = "/aggregators";
- private static final String LOGS_URL = "/logs?json";
- private static final String STATS_URL = "/stats?json";
- private static final String VERSION_URL = "/version?json";
-
- private static final DateTimeFormat FULLDATE =
- DateTimeFormat.getFormat("yyyy/MM/dd-HH:mm:ss");
-
- private final Label current_error = new Label();
-
- private final DateTimeBox start_datebox = new DateTimeBox();
- private final DateTimeBox end_datebox = new DateTimeBox();
- private final CheckBox autoreload = new CheckBox("Autoreload");
- private final ValidatedTextBox autoreoload_interval = new ValidatedTextBox();
- private Timer autoreoload_timer;
-
- private final ValidatedTextBox yrange = new ValidatedTextBox();
- private final ValidatedTextBox y2range = new ValidatedTextBox();
- private final CheckBox ylog = new CheckBox();
- private final CheckBox y2log = new CheckBox();
- private final TextBox ylabel = new TextBox();
- private final TextBox y2label = new TextBox();
- private final ValidatedTextBox yformat = new ValidatedTextBox();
- private final ValidatedTextBox y2format = new ValidatedTextBox();
- private final ValidatedTextBox wxh = new ValidatedTextBox();
-
- private String keypos = ""; // Position of the key on the graph.
- private final CheckBox horizontalkey = new CheckBox("Horizontal layout");
- private final CheckBox keybox = new CheckBox("Box");
- private final CheckBox nokey = new CheckBox("No key (overrides others)");
-
- // Styling options.
- private final CheckBox smooth = new CheckBox();
-
- /**
- * Handles every change to the query form and gets a new graph.
- * Whenever the user changes one of the parameters of the graph, we want
- * to automatically get a new graph.
- */
- private final EventsHandler refreshgraph = new EventsHandler() {
- protected <H extends EventHandler> void onEvent(final DomEvent<H> event) {
- refreshGraph();
- }
- };
-
- final MetricForm.MetricChangeHandler metric_change_handler =
- new MetricForm.MetricChangeHandler() {
- public void onMetricChange(final MetricForm metric) {
- final int index = metrics.getWidgetIndex(metric);
- metrics.getTabBar().setTabText(index, getTabTitle(metric));
- }
- private String getTabTitle(final MetricForm metric) {
- final String metrictext = metric.getMetric();
- final int last_period = metrictext.lastIndexOf('.');
- if (last_period < 0) {
- return metrictext;
- }
- return metrictext.substring(last_period + 1);
- }
- };
-
- final EventsHandler updatey2range = new EventsHandler() {
- protected <H extends EventHandler> void onEvent(final DomEvent<H> event) {
- for (final Widget metric : metrics) {
- if (!(metric instanceof MetricForm)) {
- continue;
- }
- if (((MetricForm) metric).x1y2().getValue()) {
- y2range.setEnabled(true);
- y2log.setEnabled(true);
- y2label.setEnabled(true);
- y2format.setEnabled(true);
- return;
- }
- }
- y2range.setEnabled(false);
- y2log.setEnabled(false);
- y2label.setEnabled(false);
- y2format.setEnabled(false);
- }
- };
-
- /** List of known aggregation functions. Fetched once from the server. */
- private final ArrayList<String> aggregators = new ArrayList<String>();
-
- private final DecoratedTabPanel metrics = new DecoratedTabPanel();
-
- /** Panel to place generated graphs and a box for zoom highlighting. */
- private final AbsolutePanel graphbox = new AbsolutePanel();
- private final Image graph = new Image();
- private final ZoomBox zoom_box = new ZoomBox();
- private final Label graphstatus = new Label();
- /** Remember the last URI requested to avoid requesting twice the same. */
- private String lastgraphuri;
-
- /**
- * We only send one request at a time, how many have we not sent yet?.
- * Note that we don't buffer pending requests. When there are multiple
- * ones pending, we will only execute the last one and discard the other
- * intermediate ones, since the user is no longer interested in them.
- */
- private int pending_requests = 0;
- /** How many graph requests we make. */
- private int nrequests = 0;
-
- // Other misc panels.
- private final FlexTable logs = new FlexTable();
- private final FlexTable stats_table = new FlexTable();
- private final HTML build_data = new HTML("Loading...");
-
- /**
- * This is the entry point method.
- */
- public void onModuleLoad() {
- asyncGetJson(AGGREGATORS_URL, new GotJsonCallback() {
- public void got(final JSONValue json) {
- // Do we need more manual type checking? Not sure what will happen
- // in the browser if something other than an array is returned.
- final JSONArray aggs = json.isArray();
- for (int i = 0; i < aggs.size(); i++) {
- aggregators.add(aggs.get(i).isString().stringValue());
- }
- ((MetricForm) metrics.getWidget(0)).setAggregators(aggregators);
- refreshFromQueryString();
- refreshGraph();
- }
- });
-
- // All UI elements need to regenerate the graph when changed.
- {
- final ValueChangeHandler<Date> vch = new ValueChangeHandler<Date>() {
- public void onValueChange(final ValueChangeEvent<Date> event) {
- refreshGraph();
- }
- };
- TextBox tb = start_datebox.getTextBox();
- tb.addBlurHandler(refreshgraph);
- tb.addKeyPressHandler(refreshgraph);
- start_datebox.addValueChangeHandler(vch);
- tb = end_datebox.getTextBox();
- tb.addBlurHandler(refreshgraph);
- tb.addKeyPressHandler(refreshgraph);
- end_datebox.addValueChangeHandler(vch);
- }
- autoreoload_interval.addBlurHandler(refreshgraph);
- autoreoload_interval.addKeyPressHandler(refreshgraph);
- yrange.addBlurHandler(refreshgraph);
- yrange.addKeyPressHandler(refreshgraph);
- y2range.addBlurHandler(refreshgraph);
- y2range.addKeyPressHandler(refreshgraph);
- ylog.addClickHandler(new AdjustYRangeCheckOnClick(ylog, yrange));
- y2log.addClickHandler(new AdjustYRangeCheckOnClick(y2log, y2range));
- ylog.addClickHandler(refreshgraph);
- y2log.addClickHandler(refreshgraph);
- ylabel.addBlurHandler(refreshgraph);
- ylabel.addKeyPressHandler(refreshgraph);
- y2label.addBlurHandler(refreshgraph);
- y2label.addKeyPressHandler(refreshgraph);
- yformat.addBlurHandler(refreshgraph);
- yformat.addKeyPressHandler(refreshgraph);
- y2format.addBlurHandler(refreshgraph);
- y2format.addKeyPressHandler(refreshgraph);
- wxh.addBlurHandler(refreshgraph);
- wxh.addKeyPressHandler(refreshgraph);
- horizontalkey.addClickHandler(refreshgraph);
- keybox.addClickHandler(refreshgraph);
- nokey.addClickHandler(refreshgraph);
- smooth.addClickHandler(refreshgraph);
-
- yrange.setValidationRegexp("^(" // Nothing or
- + "|\\[([-+.0-9eE]+|\\*)?" // "[start
- + ":([-+.0-9eE]+|\\*)?\\])$"); // :end]"
- yrange.setVisibleLength(5);
- yrange.setMaxLength(44); // MAX=2^26=20 chars: "[-$MAX:$MAX]"
- yrange.setText("[0:]");
-
- y2range.setValidationRegexp("^(" // Nothing or
- + "|\\[([-+.0-9eE]+|\\*)?" // "[start
- + ":([-+.0-9eE]+|\\*)?\\])$"); // :end]"
- y2range.setVisibleLength(5);
- y2range.setMaxLength(44); // MAX=2^26=20 chars: "[-$MAX:$MAX]"
- y2range.setText("[0:]");
- y2range.setEnabled(false);
- y2log.setEnabled(false);
-
- ylabel.setVisibleLength(10);
- ylabel.setMaxLength(50); // Arbitrary limit.
- y2label.setVisibleLength(10);
- y2label.setMaxLength(50); // Arbitrary limit.
- y2label.setEnabled(false);
-
- yformat.setValidationRegexp("^(|.*%..*)$"); // Nothing or at least one %?
- yformat.setVisibleLength(10);
- yformat.setMaxLength(16); // Arbitrary limit.
- y2format.setValidationRegexp("^(|.*%..*)$"); // Nothing or at least one %?
- y2format.setVisibleLength(10);
- y2format.setMaxLength(16); // Arbitrary limit.
- y2format.setEnabled(false);
-
- wxh.setValidationRegexp("^[1-9][0-9]{2,}x[1-9][0-9]{2,}$"); // 100x100
- wxh.setVisibleLength(9);
- wxh.setMaxLength(11); // 99999x99999
- wxh.setText((Window.getClientWidth() - 20) + "x"
- + (Window.getClientHeight() * 4 / 5));
-
- final FlexTable table = new FlexTable();
- table.setText(0, 0, "From");
- {
- final HorizontalPanel hbox = new HorizontalPanel();
- hbox.add(new InlineLabel("To"));
- final Anchor now = new Anchor("(now)");
- now.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- end_datebox.setValue(new Date());
- refreshGraph();
- }
- });
- hbox.add(now);
- hbox.add(autoreload);
- hbox.setWidth("100%");
- table.setWidget(0, 1, hbox);
- }
- autoreload.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
- @Override
- public void onValueChange(final ValueChangeEvent<Boolean> event) {
- if (autoreload.getValue()) {
- final HorizontalPanel hbox = new HorizontalPanel();
- hbox.setWidth("100%");
- hbox.add(new InlineLabel("Every:"));
- hbox.add(autoreoload_interval);
- hbox.add(new InlineLabel("seconds"));
- table.setWidget(1, 1, hbox);
- if (autoreoload_interval.getValue().isEmpty()) {
- autoreoload_interval.setValue("15");
- }
- autoreoload_interval.setFocus(true);
- lastgraphuri = ""; // Force refreshGraph.
- refreshGraph(); // Trigger the 1st auto-reload
- } else {
- table.setWidget(1, 1, end_datebox);
- }
- }
- });
- autoreoload_interval.setValidationRegexp("^([5-9]|[1-9][0-9]+)$"); // >=5s
- autoreoload_interval.setMaxLength(4);
- autoreoload_interval.setVisibleLength(8);
-
- table.setWidget(1, 0, start_datebox);
- table.setWidget(1, 1, end_datebox);
- {
- final HorizontalPanel hbox = new HorizontalPanel();
- hbox.add(new InlineLabel("WxH:"));
- hbox.add(wxh);
- table.setWidget(0, 3, hbox);
- }
- {
- addMetricForm("metric 1", 0);
- metrics.selectTab(0);
- metrics.add(new InlineLabel("Loading..."), "+");
- metrics.addBeforeSelectionHandler(new BeforeSelectionHandler<Integer>() {
- public void onBeforeSelection(final BeforeSelectionEvent<Integer> event) {
- final int item = event.getItem();
- final int nitems = metrics.getWidgetCount();
- if (item == nitems - 1) { // Last item: the "+" was clicked.
- event.cancel();
- final MetricForm metric = addMetricForm("metric " + nitems, item);
- metrics.selectTab(item);
- metric.setFocus(true);
- }
- }
- });
- table.setWidget(2, 0, metrics);
- }
- table.getFlexCellFormatter().setColSpan(2, 0, 2);
- table.getFlexCellFormatter().setRowSpan(1, 3, 2);
- final DecoratedTabPanel optpanel = new DecoratedTabPanel();
- optpanel.add(makeAxesPanel(), "Axes");
- optpanel.add(makeKeyPanel(), "Key");
- optpanel.add(makeStylePanel(), "Style");
- optpanel.selectTab(0);
- table.setWidget(1, 3, optpanel);
-
- final DecoratorPanel decorator = new DecoratorPanel();
- decorator.setWidget(table);
- final VerticalPanel graphpanel = new VerticalPanel();
- graphpanel.add(decorator);
- {
- final VerticalPanel graphvbox = new VerticalPanel();
- graphvbox.add(graphstatus);
-
- graph.setVisible(false);
-
- // Put the graph image element and the zoombox elements inside the absolute panel
- graphbox.add(graph, 0, 0);
- zoom_box.setVisible(false);
- graphbox.add(zoom_box, 0, 0);
-
- graphvbox.add(graphbox);
- graph.addErrorHandler(new ErrorHandler() {
- public void onError(final ErrorEvent event) {
- graphstatus.setText("Oops, failed to load the graph.");
- }
- });
- graph.addLoadHandler(new LoadHandler() {
- public void onLoad(final LoadEvent event) {
- graphbox.setWidth(graph.getWidth() + "px");
- graphbox.setHeight(graph.getHeight() + "px");
- }
- });
-
- graphpanel.add(graphvbox);
- }
- final DecoratedTabPanel mainpanel = new DecoratedTabPanel();
- mainpanel.setWidth("100%");
- mainpanel.add(graphpanel, "Graph");
- mainpanel.add(stats_table, "Stats");
- mainpanel.add(logs, "Logs");
- mainpanel.add(build_data, "Version");
- mainpanel.selectTab(0);
- mainpanel.addBeforeSelectionHandler(new BeforeSelectionHandler<Integer>() {
- public void onBeforeSelection(final BeforeSelectionEvent<Integer> event) {
- clearError();
- final int item = event.getItem();
- switch (item) {
- case 1: refreshStats(); return;
- case 2: refreshLogs(); return;
- case 3: refreshVersion(); return;
- }
- }
- });
- final VerticalPanel root = new VerticalPanel();
- root.setWidth("100%");
- root.add(current_error);
- current_error.setVisible(false);
- current_error.addStyleName("dateBoxFormatError");
- root.add(mainpanel);
- RootPanel.get("queryuimain").add(root);
- // Must be done at the end, once all the widgets are attached.
- ensureSameWidgetSize(optpanel);
-
- History.addHistoryListener(this);
- }
-
- @Override
- public void onHistoryChanged(String historyToken) {
- refreshFromQueryString();
- refreshGraph();
- }
-
- /** Additional styling options. */
- private Grid makeStylePanel() {
- final Grid grid = new Grid(5, 3);
- grid.setText(0, 1, "Smooth");
- grid.setWidget(0, 2, smooth);
- return grid;
- }
-
- /**
- * Builds the panel containing customizations for the axes of the graph.
- */
- private Grid makeAxesPanel() {
- final Grid grid = new Grid(5, 3);
- grid.setText(0, 1, "Y");
- grid.setText(0, 2, "Y2");
- setTextAlignCenter(grid.getRowFormatter().getElement(0));
- grid.setText(1, 0, "Label");
- grid.setWidget(1, 1, ylabel);
- grid.setWidget(1, 2, y2label);
- grid.setText(2, 0, "Format");
- grid.setWidget(2, 1, yformat);
- grid.setWidget(2, 2, y2format);
- grid.setText(3, 0, "Range");
- grid.setWidget(3, 1, yrange);
- grid.setWidget(3, 2, y2range);
- grid.setText(4, 0, "Log scale");
- grid.setWidget(4, 1, ylog);
- grid.setWidget(4, 2, y2log);
- setTextAlignCenter(grid.getCellFormatter().getElement(4, 1));
- setTextAlignCenter(grid.getCellFormatter().getElement(4, 2));
- return grid;
- }
-
- private MetricForm addMetricForm(final String label, final int item) {
- final MetricForm metric = new MetricForm(refreshgraph);
- metric.x1y2().addClickHandler(updatey2range);
- metric.setMetricChangeHandler(metric_change_handler);
- metric.setAggregators(aggregators);
- metrics.insert(metric, label, item);
- return metric;
- }
-
- private final HashMap<String, RadioButton> keypos_map =
- new HashMap<String, RadioButton>(17);
-
- /**
- * Small helper to build a radio button used to change the position of the
- * key of the graph.
- */
- private RadioButton addKeyRadioButton(final Grid grid,
- final int row, final int col,
- final String pos) {
- final RadioButton rb = new RadioButton("keypos");
- rb.addClickHandler(new ClickHandler() {
- public void onClick(final ClickEvent event) {
- keypos = pos;
- }
- });
- rb.addClickHandler(refreshgraph);
- grid.setWidget(row, col, rb);
- keypos_map.put(pos, rb);
- return rb;
- }
-
- /**
- * Builds the panel containing the customizations for the key of the graph.
- */
- private Widget makeKeyPanel() {
- final Grid grid = new Grid(5, 5);
- addKeyRadioButton(grid, 0, 0, "out left top");
- addKeyRadioButton(grid, 0, 2, "out center top");
- addKeyRadioButton(grid, 0, 4, "out right top");
- addKeyRadioButton(grid, 1, 1, "top left");
- addKeyRadioButton(grid, 1, 2, "top center");
- addKeyRadioButton(grid, 1, 3, "top right").setValue(true);
- addKeyRadioButton(grid, 2, 0, "out center left");
- addKeyRadioButton(grid, 2, 1, "center left");
- addKeyRadioButton(grid, 2, 2, "center");
- addKeyRadioButton(grid, 2, 3, "center right");
- addKeyRadioButton(grid, 2, 4, "out center right");
- addKeyRadioButton(grid, 3, 1, "bottom left");
- addKeyRadioButton(grid, 3, 2, "bottom center");
- addKeyRadioButton(grid, 3, 3, "bottom right");
- addKeyRadioButton(grid, 4, 0, "out bottom left");
- addKeyRadioButton(grid, 4, 2, "out bottom center");
- addKeyRadioButton(grid, 4, 4, "out bottom right");
- final Grid.CellFormatter cf = grid.getCellFormatter();
- cf.getElement(1, 1).getStyle().setProperty("borderLeft", "1px solid #000");
- cf.getElement(1, 1).getStyle().setProperty("borderTop", "1px solid #000");
- cf.getElement(1, 2).getStyle().setProperty("borderTop", "1px solid #000");
- cf.getElement(1, 3).getStyle().setProperty("borderTop", "1px solid #000");
- cf.getElement(1, 3).getStyle().setProperty("borderRight", "1px solid #000");
- cf.getElement(2, 1).getStyle().setProperty("borderLeft", "1px solid #000");
- cf.getElement(2, 3).getStyle().setProperty("borderRight", "1px solid #000");
- cf.getElement(3, 1).getStyle().setProperty("borderLeft", "1px solid #000");
- cf.getElement(3, 1).getStyle().setProperty("borderBottom", "1px solid #000");
- cf.getElement(3, 2).getStyle().setProperty("borderBottom", "1px solid #000");
- cf.getElement(3, 3).getStyle().setProperty("borderBottom", "1px solid #000");
- cf.getElement(3, 3).getStyle().setProperty("borderRight", "1px solid #000");
- final VerticalPanel vbox = new VerticalPanel();
- vbox.add(new InlineLabel("Key location:"));
- vbox.add(grid);
- vbox.add(horizontalkey);
- keybox.setValue(true);
- vbox.add(keybox);
- vbox.add(nokey);
- return vbox;
- }
-
- private void refreshStats() {
- asyncGetJson(STATS_URL, new GotJsonCallback() {
- public void got(final JSONValue json) {
- final JSONArray stats = json.isArray();
- final int nstats = stats.size();
- for (int i = 0; i < nstats; i++) {
- final String stat = stats.get(i).isString().stringValue();
- String part = stat.substring(0, stat.indexOf(' '));
- stats_table.setText(i, 0, part); // metric
- int pos = part.length() + 1;
- part = stat.substring(pos, stat.indexOf(' ', pos));
- stats_table.setText(i, 1, part); // timestamp
- pos += part.length() + 1;
- part = stat.substring(pos, stat.indexOf(' ', pos));
- stats_table.setText(i, 2, part); // value
- pos += part.length() + 1;
- stats_table.setText(i, 3, stat.substring(pos)); // tags
- }
- }
- });
- }
-
- private void refreshVersion() {
- asyncGetJson(VERSION_URL, new GotJsonCallback() {
- public void got(final JSONValue json) {
- final JSONObject bd = json.isObject();
- final JSONString shortrev = bd.get("short_revision").isString();
- final JSONString status = bd.get("repo_status").isString();
- final JSONNumber stamp = bd.get("timestamp").isNumber();
- final JSONString user = bd.get("user").isString();
- final JSONString host = bd.get("host").isString();
- final JSONString repo = bd.get("repo").isString();
- build_data.setHTML(
- "OpenTSDB built from revision " + shortrev.stringValue()
- + " in a " + status.stringValue() + " state<br/>"
- + "Built on " + new Date((long) (stamp.doubleValue() * 1000))
- + " by " + user.stringValue() + '@' + host.stringValue()
- + ':' + repo.stringValue());
- }
- });
- }
-
- private void refreshLogs() {
- asyncGetJson(LOGS_URL, new GotJsonCallback() {
- public void got(final JSONValue json) {
- final JSONArray logmsgs = json.isArray();
- final int nmsgs = logmsgs.size();
- final FlexTable.FlexCellFormatter fcf = logs.getFlexCellFormatter();
- final FlexTable.RowFormatter rf = logs.getRowFormatter();
- for (int i = 0; i < nmsgs; i++) {
- final String msg = logmsgs.get(i).isString().stringValue();
- String part = msg.substring(0, msg.indexOf('\t'));
- logs.setText(i * 2, 0,
- new Date(Integer.valueOf(part) * 1000L).toString());
- logs.setText(i * 2 + 1, 0, ""); // So we can change the style ahead.
- int pos = part.length() + 1;
- part = msg.substring(pos, msg.indexOf('\t', pos));
- if ("WARN".equals(part)) {
- rf.getElement(i * 2).getStyle().setBackgroundColor("#FCC");
- rf.getElement(i * 2 + 1).getStyle().setBackgroundColor("#FCC");
- } else if ("ERROR".equals(part)) {
- rf.getElement(i * 2).getStyle().setBackgroundColor("#F99");
- rf.getElement(i * 2 + 1).getStyle().setBackgroundColor("#F99");
- } else {
- rf.getElement(i * 2).getStyle().clearBackgroundColor();
- rf.getElement(i * 2 + 1).getStyle().clearBackgroundColor();
- if ((i % 2) == 0) {
- rf.addStyleName(i * 2, "subg");
- rf.addStyleName(i * 2 + 1, "subg");
- }
- }
- pos += part.length() + 1;
- logs.setText(i * 2, 1, part); // level
- part = msg.substring(pos, msg.indexOf('\t', pos));
- pos += part.length() + 1;
- logs.setText(i * 2, 2, part); // thread
- part = msg.substring(pos, msg.indexOf('\t', pos));
- pos += part.length() + 1;
- if (part.startsWith("net.opentsdb.")) {
- part = part.substring(13);
- } else if (part.startsWith("org.hbase.")) {
- part = part.substring(10);
- }
- logs.setText(i * 2, 3, part); // logger
- logs.setText(i * 2 + 1, 0, msg.substring(pos)); // message
- fcf.setColSpan(i * 2 + 1, 0, 4);
- rf.addStyleName(i * 2, "fwf");
- rf.addStyleName(i * 2 + 1, "fwf");
- }
- }
- });
- }
-
- private void addLabels(final StringBuilder url) {
- final String ylabel = this.ylabel.getText();
- if (!ylabel.isEmpty()) {
- url.append("&ylabel=").append(URL.encodeComponent(ylabel));
- }
- if (y2label.isEnabled()) {
- final String y2label = this.y2label.getText();
- if (!y2label.isEmpty()) {
- url.append("&y2label=").append(URL.encodeComponent(y2label));
- }
- }
- }
-
- private void addFormats(final StringBuilder url) {
- final String yformat = this.yformat.getText();
- if (!yformat.isEmpty()) {
- url.append("&yformat=").append(URL.encodeComponent(yformat));
- }
- if (y2format.isEnabled()) {
- final String y2format = this.y2format.getText();
- if (!y2format.isEmpty()) {
- url.append("&y2format=").append(URL.encodeComponent(y2format));
- }
- }
- }
-
- private void addYRanges(final StringBuilder url) {
- final String yrange = this.yrange.getText();
- if (!yrange.isEmpty()) {
- url.append("&yrange=").append(yrange);
- }
- if (y2range.isEnabled()) {
- final String y2range = this.y2range.getText();
- if (!y2range.isEmpty()) {
- url.append("&y2range=").append(y2range);
- }
- }
- }
-
- private void addLogscales(final StringBuilder url) {
- if (ylog.getValue()) {
- url.append("&ylog");
- }
- if (y2log.isEnabled() && y2log.getValue()) {
- url.append("&y2log");
- }
- }
-
- /**
- * Maybe sets the text of a {@link TextBox} from a query string parameter.
- * @param qs A parsed query string.
- * @param key Name of the query string parameter.
- * If this parameter wasn't passed, the {@link TextBox} will be emptied.
- * @param tb The {@link TextBox} to change.
- */
- private static void maybeSetTextbox(final QueryString qs,
- final String key,
- final TextBox tb) {
- final ArrayList<String> values = qs.get(key);
- if (values == null) {
- tb.setText("");
- return;
- }
- tb.setText(values.get(0));
- }
-
- /**
- * Sets the text of a {@link TextBox} from a query string parameter.
- * @param qs A parsed query string.
- * @param key Name of the query string parameter.
- * @param tb The {@link TextBox} to change.
- */
- private static void setTextbox(final QueryString qs,
- final String key,
- final TextBox tb) {
- final ArrayList<String> values = qs.get(key);
- if (values != null) {
- tb.setText(values.get(0));
- }
- }
-
- private static QueryString getQueryString(final String qs) {
- return qs.isEmpty() ? new QueryString() : QueryString.decode(qs);
- }
-
- private void refreshFromQueryString() {
- final QueryString qs = getQueryString(History.getToken());
-
- maybeSetTextbox(qs, "start", start_datebox.getTextBox());
- maybeSetTextbox(qs, "end", end_datebox.getTextBox());
- setTextbox(qs, "wxh", wxh);
- autoreload.setValue(qs.containsKey("autoreload"), true);
- maybeSetTextbox(qs, "autoreload", autoreoload_interval);
-
- final ArrayList<String> newmetrics = qs.get("m");
- if (newmetrics == null) { // Clear all metric forms.
- final int toremove = metrics.getWidgetCount() - 1;
- addMetricForm("metric 1", 0);
- metrics.selectTab(0);
- for (int i = 0; i < toremove; i++) {
- metrics.remove(1);
- }
- return;
- }
- final int n = newmetrics.size(); // We want this many metrics.
- ArrayList<String> options = qs.get("o");
- if (options == null) {
- options = new ArrayList<String>(n);
- }
- for (int i = options.size(); i < n; i++) { // Make both arrays equal size.
- options.add(""); // Add missing o's.
- }
-
- for (int i = 0; i < newmetrics.size(); ++i) {
- if (i == metrics.getWidgetCount() - 1) {
- addMetricForm("", i);
- }
-
- final MetricForm metric = (MetricForm) metrics.getWidget(i);
- metric.updateFromQueryString(newmetrics.get(i), options.get(i));
- }
- // Remove extra metric forms.
- final int m = metrics.getWidgetCount() - 1; // We have this many metrics.
- int showing = metrics.getTabBar().getSelectedTab(); // Currently selected.
- for (int i = m - 1; i >= n; i--) {
- if (showing == i) { // If we're about to remove the currently selected,
- metrics.selectTab(--showing); // fix focus to not wind up nowhere.
- }
- metrics.remove(i);
- }
- updatey2range.onEvent(null);
-
- maybeSetTextbox(qs, "ylabel", ylabel);
- maybeSetTextbox(qs, "y2label", y2label);
- maybeSetTextbox(qs, "yformat", yformat);
- maybeSetTextbox(qs, "y2format", y2format);
- maybeSetTextbox(qs, "yrange", yrange);
- maybeSetTextbox(qs, "y2range", y2range);
- ylog.setValue(qs.containsKey("ylog"));
- y2log.setValue(qs.containsKey("y2log"));
-
- if (qs.containsKey("key")) {
- final String key = qs.getFirst("key");
- keybox.setValue(key.contains(" box"));
- horizontalkey.setValue(key.contains(" horiz"));
- keypos = key.replaceAll(" (box|horiz\\w*)", "");
- keypos_map.get(keypos).setChecked(true);
- } else {
- keybox.setValue(false);
- horizontalkey.setValue(false);
- keypos_map.get("top right").setChecked(true);
- keypos = "";
- }
- nokey.setValue(qs.containsKey("nokey"));
- smooth.setValue(qs.containsKey("smooth"));
- }
-
- private void refreshGraph() {
- final Date start = start_datebox.getValue();
- if (start == null) {
- graphstatus.setText("Please specify a start time.");
- return;
- }
- final Date end = end_datebox.getValue();
- if (end != null && !autoreload.getValue()) {
- if (end.getTime() <= start.getTime()) {
- end_datebox.addStyleName("dateBoxFormatError");
- graphstatus.setText("End time must be after start time!");
- return;
- }
- }
- final StringBuilder url = new StringBuilder();
- url.append("/q?start=").append(FULLDATE.format(start));
- if (end != null && !autoreload.getValue()) {
- url.append("&end=").append(FULLDATE.format(end));
- } else {
- // If there's no end-time, the graph may change while the URL remains
- // the same. No browser seems to re-fetch an image once it's been
- // fetched, even if we destroy the DOM object and re-created it with the
- // same src attribute. This has nothing to do with caching headers sent
- // by the server. The browsers simply won't retrieve the same URL again
- // through JavaScript manipulations, period. So as a workaround, we add
- // a special parameter that the server will delete from the query.
- url.append("&ignore=" + nrequests++);
- }
- if (!addAllMetrics(url)) {
- return;
- }
- addLabels(url);
- addFormats(url);
- addYRanges(url);
- addLogscales(url);
- if (nokey.getValue()) {
- url.append("&nokey");
- } else if (!keypos.isEmpty() || horizontalkey.getValue()) {
- url.append("&key=");
- if (!keypos.isEmpty()) {
- url.append(keypos);
- }
- if (horizontalkey.getValue()) {
- url.append(" horiz");
- }
- if (keybox.getValue()) {
- url.append(" box");
- }
- }
- url.append("&wxh=").append(wxh.getText());
- if (smooth.getValue()) {
- url.append("&smooth=csplines");
- }
- final String uri = url.toString();
- if (uri.equals(lastgraphuri)) {
- return; // Don't re-request the same graph.
- } else if (pending_requests++ > 0) {
- return;
- }
- lastgraphuri = uri;
- graphstatus.setText("Loading graph...");
- asyncGetJson(uri + "&json", new GotJsonCallback() {
- public void got(final JSONValue json) {
- if (autoreoload_timer != null) {
- autoreoload_timer.cancel();
- autoreoload_timer = null;
- }
- final JSONObject result = json.isObject();
- final JSONValue err = result.get("err");
- String msg = "";
- if (err != null) {
- displayError("An error occurred while generating the graph: "
- + err.isString().stringValue());
- graphstatus.setText("Please correct the error above.");
- } else {
- clearError();
-
- String history = uri.substring(3) // Remove "/q?".
- .replaceFirst("ignore=[^&]*&", ""); // Unnecessary cruft.
- if (autoreload.getValue()) {
- history += "&autoreload=" + autoreoload_interval.getText();
- }
- if (!history.equals(History.getToken())) {
- History.newItem(history, false);
- }
-
- final JSONValue nplotted = result.get("plotted");
- final JSONValue cachehit = result.get("cachehit");
- if (cachehit != null) {
- msg += "Cache hit (" + cachehit.isString().stringValue() + "). ";
- }
- if (nplotted != null && nplotted.isNumber().doubleValue() > 0) {
- graph.setUrl(uri + "&png");
- graph.setVisible(true);
-
- msg += result.get("points").isNumber() + " points retrieved, "
- + nplotted + " points plotted";
- } else {
- graph.setVisible(false);
- msg += "Your query didn't return anything";
- }
- final JSONValue timing = result.get("timing");
- if (timing != null) {
- msg += " in " + timing + "ms.";
- } else {
- msg += '.';
- }
- }
- final JSONValue info = result.get("info");
- if (info != null) {
- if (!msg.isEmpty()) {
- msg += ' ';
- }
- msg += info.isString().stringValue();
- }
- graphstatus.setText(msg);
- if (result.get("etags") != null) {
- final JSONArray etags = result.get("etags").isArray();
- final int netags = etags.size();
- for (int i = 0; i < netags; i++) {
- if (i >= metrics.getWidgetCount()) {
- break;
- }
- final Widget widget = metrics.getWidget(i);
- if (!(widget instanceof MetricForm)) {
- break;
- }
- final MetricForm metric = (MetricForm) widget;
- final JSONArray tags = etags.get(i).isArray();
- final int ntags = tags.size();
- for (int j = 0; j < ntags; j++) {
- metric.autoSuggestTag(tags.get(j).isString().stringValue());
- }
- }
- }
- if (autoreload.getValue()) {
- final int reload_in = Integer.parseInt(autoreoload_interval.getValue());
- if (reload_in >= 5) {
- autoreoload_timer = new Timer() {
- public void run() {
- // Verify that we still want auto reload and that the graph
- // hasn't been updated in the mean time.
- if (autoreload.getValue() && lastgraphuri == uri) {
- // Force refreshGraph to believe that we want a new graph.
- lastgraphuri = "";
- refreshGraph();
- }
- }
- };
- autoreoload_timer.schedule(reload_in * 1000);
- }
- }
- if (--pending_requests > 0) {
- pending_requests = 0;
- refreshGraph();
- }
- }
- });
- }
-
- private boolean addAllMetrics(final StringBuilder url) {
- boolean found_metric = false;
- for (final Widget widget : metrics) {
- if (!(widget instanceof MetricForm)) {
- continue;
- }
- final MetricForm metric = (MetricForm) widget;
- found_metric |= metric.buildQueryString(url);
- }
- if (!found_metric) {
- graphstatus.setText("Please specify a metric.");
- }
- return found_metric;
- }
-
- private void asyncGetJson(final String url, final GotJsonCallback callback) {
- final RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, url);
- try {
- builder.sendRequest(null, new RequestCallback() {
- public void onError(final Request request, final Throwable e) {
- displayError("Failed to get " + url + ": " + e.getMessage());
- // Since we don't call the callback we've been given, reset this
- // bit of state as we're not going to retry anything right now.
- pending_requests = 0;
- }
-
- public void onResponseReceived(final Request request,
- final Response response) {
- final int code = response.getStatusCode();
- if (code == Response.SC_OK) {
- clearError();
- callback.got(JSONParser.parse(response.getText()));
- return;
- } else if (code >= Response.SC_BAD_REQUEST) { // 400+ => Oops.
- // Since we don't call the callback we've been given, reset this
- // bit of state as we're not going to retry anything right now.
- pending_requests = 0;
- String err = response.getText();
- // If the response looks like a JSON object, it probably contains
- // an error message.
- if (!err.isEmpty() && err.charAt(0) == '{') {
- final JSONValue json = JSONParser.parse(err);
- final JSONObject result = json == null ? null : json.isObject();
- final JSONValue jerr = result == null ? null : result.get("err");
- final JSONString serr = jerr == null ? null : jerr.isString();
- err = serr.stringValue();
- // If the error message has multiple lines (which is common if
- // it contains a stack trace), show only the first line and
- // hide the rest in a panel users can expand.
- final int newline = err.indexOf('\n', 1);
- final String msg = "Request failed: " + response.getStatusText();
- if (newline < 0) {
- displayError(msg + ": " + err);
- } else {
- displayError(msg);
- final DisclosurePanel dp =
- new DisclosurePanel(err.substring(0, newline));
- RootPanel.get("queryuimain").add(dp); // Attach the widget.
- final InlineLabel content =
- new InlineLabel(err.substring(newline, err.length()));
- content.addStyleName("fwf"); // For readable stack traces.
- dp.setContent(content);
- current_error.getElement().appendChild(dp.getElement());
- }
- } else {
- displayError("Request failed while getting " + url + ": "
- + response.getStatusText());
- // Since we don't call the callback we've been given, reset this
- // bit of state as we're not going to retry anything right now.
- pending_requests = 0;
- }
- graphstatus.setText("");
- }
- }
- });
- } catch (RequestException e) {
- displayError("Failed to get " + url + ": " + e.getMessage());
- }
- }
-
- private void displayError(final String errmsg) {
- current_error.setText(errmsg);
- current_error.setVisible(true);
- }
-
- private void clearError() {
- current_error.setVisible(false);
- }
-
- static void setTextAlignCenter(final Element element) {
- element.getStyle().setProperty("textAlign", "center");
- }
-
- /** Zoom box and associated event handlers. */
- private final class ZoomBox extends HTML
- implements MouseUpHandler, MouseMoveHandler, MouseDownHandler {
-
- /** "Fudge factor" to account for the axes present on the image. */
- private static final int OFFSET_WITH_AXIS = 45;
- private static final int OFFSET_WITHOUT_AXIS = 15;
-
- private boolean zoom_selection_active = false;
- /** Rectangle of the selection. */
- private int start_x;
- private int end_x;
- private int start_y;
- private int end_y;
-
- private HandlerRegistration graph_move_handler;
- private HandlerRegistration box_move_handler;
-
- ZoomBox() {
- // Set ourselves up as the event handler for all mouse-draggable events.
- graph.addMouseDownHandler(this);
- graph.addMouseUpHandler(this);
-
- // Also add the handlers on the actual zoom highlight box (this is in
- // case the cursor gets on the zoombox, so that it keeps responding
- // correctly).
- super.addMouseUpHandler(this);
-
- final Style style = super.getElement().getStyle();
- style.setProperty("background", "red");
- style.setProperty("filter", "alpha(opacity=50)");
- style.setProperty("opacity", "0.4");
- }
-
- @Override
- public void onMouseDown(final MouseDownEvent event) {
- // Check if the zoom selection is active, if so, it's possible that the
- // mouse left the browser mid-selection and got stuck enabled even
- // though the mouse isn't still pressed. If that's the case, do a similar
- // operation to the onMouseUp event.
- if (zoom_selection_active) {
- endSelection(event);
- return;
- }
-
- final Element image = graph.getElement();
- zoom_selection_active = true;
- start_x = event.getRelativeX(image);
- start_y = event.getRelativeY(image);
- end_x = 0;
- end_y = 0;
-
- graphbox.setWidgetPosition(this, start_x, start_y);
- super.setWidth("0px");
- super.setHeight("0px");
- super.setVisible(true);
-
- graph_move_handler = graph.addMouseMoveHandler(this);
- box_move_handler = super.addMouseMoveHandler(this);
- }
-
- @Override
- public void onMouseMove(final MouseMoveEvent event) {
- event.preventDefault();
-
- final int x = event.getRelativeX(graph.getElement());
- final int y = event.getRelativeY(graph.getElement());
- int left;
- int top;
- int width;
- int height;
-
- // Figure out the top, left, height, and width of the box based
- // on current cursor location.
- if (x < start_x) {
- left = x;
- width = start_x - x;
- } else {
- left = start_x;
- width = x - start_x;
- }
- if (y < start_y) {
- top = y;
- height = start_y - y;
- } else {
- top = start_y;
- height = y - start_y;
- }
-
- // Resize / move the box as needed based on cursor location.
- super.setVisible(false);
- graphbox.setWidgetPosition(this, left, top);
- super.setWidth(width + "px");
- super.setHeight(height + "px");
- super.setVisible(true);
- }
-
- @Override
- public void onMouseUp(final MouseUpEvent event) {
- if (zoom_selection_active) {
- endSelection(event);
- }
- }
-
- /**
- * Perform operations for when a user completes their selection.
- * This involves removing the highlight box and kicking off the
- * zoom in operation.
- * @param event The event that triggered the end of the selection.
- */
- private <H extends EventHandler> void endSelection(final MouseEvent<H> event) {
- zoom_selection_active = false;
-
- // Stop tracking cursor movements to improve performance.
- graph_move_handler.removeHandler();
- graph_move_handler = null;
- box_move_handler.removeHandler();
- box_move_handler = null;
-
- final Element image = graph.getElement();
- end_x = event.getRelativeX(image);
- end_y = event.getRelativeY(image);
-
- // Hide the zoom box
- super.setVisible(false);
- super.setWidth("0px");
- super.setHeight("0px");
-
- // Calculate the true start/end points of the zoom area selected by
- // mouse. If the mouse was dragged left on the graph before being
- // let up, then start_x is the right-most edge of the zoomable area.
- // If the mouse was dragged right on the graph before being let up,
- // then start_x is the left-most edge of the zoomable area.
- if (start_x < end_x) {
- start_x = start_x - OFFSET_WITH_AXIS;
- end_x = end_x - OFFSET_WITH_AXIS;
- } else {
- final int saved_start = start_x;
- start_x = end_x - OFFSET_WITH_AXIS;
- end_x = saved_start - OFFSET_WITH_AXIS;
- }
- int actual_width = graph.getWidth() - OFFSET_WITH_AXIS;
- if (y2range.isEnabled()) { // If we have a second Y axis.
- actual_width -= OFFSET_WITH_AXIS;
- } else {
- actual_width -= OFFSET_WITHOUT_AXIS;
- }
-
- // Prevent division by zero if image is pathologically small.
- // or: Prevent changing anything if the distance the cursor traveled was
- // too small (as happens during a simple click or unintentional click).
- if (actual_width < 1 || end_x - start_x <= 5) {
- return;
- }
-
- // Total span of time represented between the start and end times.
- final long duration;
- final long start = start_datebox.getValue().getTime();
- {
- final long end;
- final Date end_date = end_datebox.getValue();
- if (end_date != null) {
- end = end_date.getTime();
- } else {
- end = new Date().getTime();
- }
- duration = end - start;
- }
-
- // Get the start and end positions of the mouse drag operation on the
- // image as a percentage of the image size.
- final long start_change = start_x * duration / actual_width;
- final long end_change = end_x * duration / actual_width;
-
- start_datebox.setValue(new Date(start + start_change));
- end_datebox.setValue(new Date(start + end_change));
- refreshGraph();
- }
-
- };
-
- private final class AdjustYRangeCheckOnClick implements ClickHandler {
-
- private final CheckBox box;
- private final ValidatedTextBox range;