summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShireesh Anjal <shireesh@gluster.com>2011-04-26 20:09:44 +0530
committerShireesh Anjal <shireesh@gluster.com>2011-04-30 22:40:53 +0530
commitffcf099e6186502e750676b9b266963d23c62756 (patch)
tree1799489d61e49fa4b860fa57bdbc077094c45db7 /src
parent9c749f036a5f6efd83b3d5fd8e90681916448db4 (diff)
Story#34 - Volume logs
Diffstat (limited to 'src')
-rw-r--r--src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java9
-rw-r--r--src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java57
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java4
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java35
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java3
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/adapters/VolumeLogDateAdapter.java12
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java88
-rw-r--r--src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java9
-rw-r--r--src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java149
-rw-r--r--src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java97
10 files changed, 409 insertions, 54 deletions
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java
index da3ac279..41d76e58 100644
--- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java
+++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/GlusterDataModelManager.java
@@ -180,13 +180,8 @@ public class GlusterDataModelManager {
s2dc = new Disk(server2, "sdc", 200d, -1d, DISK_STATUS.UNINITIALIZED);
s2dd = new Disk(server2, "sdd", 200d, 124.89, DISK_STATUS.READY);
- s3da = new Disk(server3, "NA", -1d, -1d, DISK_STATUS.OFFLINE); // disk
- // name
- // unavailable
- // since
- // server
- // is
- // offline
+ // disk name unavailable since server is offline
+ s3da = new Disk(server3, "NA", -1d, -1d, DISK_STATUS.OFFLINE);
s4da = new Disk(server4, "sda", 100d, 85.39, DISK_STATUS.READY);
diff --git a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java
index 87e02e28..33791a50 100644
--- a/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java
+++ b/src/com.gluster.storage.management.client/src/com/gluster/storage/management/client/VolumesClient.java
@@ -20,12 +20,13 @@
*/
package com.gluster.storage.management.client;
-
import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
-
import javax.ws.rs.core.MultivaluedMap;
+import com.gluster.storage.management.core.constants.CoreConstants;
+import com.gluster.storage.management.core.constants.GlusterConstants;
import com.gluster.storage.management.core.constants.RESTConstants;
import com.gluster.storage.management.core.model.Disk;
import com.gluster.storage.management.core.model.Disk.DISK_STATUS;
@@ -34,13 +35,13 @@ import com.gluster.storage.management.core.model.Volume;
import com.gluster.storage.management.core.response.LogMessageListResponse;
import com.gluster.storage.management.core.response.VolumeListResponse;
import com.gluster.storage.management.core.response.VolumeOptionInfoListResponse;
+import com.gluster.storage.management.core.utils.DateUtil;
import com.gluster.storage.management.core.utils.GlusterCoreUtil;
import com.gluster.storage.management.core.utils.StringUtil;
import com.sun.jersey.api.representation.Form;
import com.sun.jersey.core.util.MultivaluedMapImpl;
public class VolumesClient extends AbstractClient {
-
public VolumesClient(String securityToken) {
super(securityToken);
}
@@ -110,13 +111,55 @@ public class VolumesClient extends AbstractClient {
return (Status) postRequest(volumeName + "/" + RESTConstants.SUBRESOURCE_DISKS, Status.class, form);
}
- public LogMessageListResponse getLogs(String volumeName, int lineCount) {
- MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
- queryParams.add(RESTConstants.QUERY_PARAM_LINE_COUNT, "" + lineCount);
- // TODO: Add other filte criteria as query parameters
+ /**
+ * Fetches volume logs for the given volume based on given filter criteria
+ *
+ * @param volumeName
+ * Name of volume whose logs are to be fetched
+ * @param diskName
+ * Name of the disk whose logs are to be fetched. Pass ALL to fetch log messages from all disks of the
+ * volume.
+ * @param severity
+ * Log severity {@link GlusterConstants#VOLUME_LOG_LEVELS_ARR}. Pass ALL to fetch log messages of all
+ * severity levels.
+ * @param fromTimestamp
+ * From timestamp. Pass null if this filter is not required.
+ * @param toTimestamp
+ * To timestamp. Pass null if this filter is not required.
+ * @param messageCount
+ * Number of most recent log messages to be fetched (from each disk)
+ * @return Log Message List response received from the Gluster Management Server.
+ */
+ public LogMessageListResponse getLogs(String volumeName, String diskName, String severity, Date fromTimestamp, Date toTimestamp, int messageCount) {
+ MultivaluedMap<String, String> queryParams = prepareGetLogQueryParams(diskName, severity, fromTimestamp,
+ toTimestamp, messageCount);
+
return (LogMessageListResponse) fetchSubResource(volumeName + "/" + RESTConstants.SUBRESOURCE_LOGS,
queryParams, LogMessageListResponse.class);
+ }
+ private MultivaluedMap<String, String> prepareGetLogQueryParams(String diskName, String severity,
+ Date fromTimestamp, Date toTimestamp, int messageCount) {
+ MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
+ queryParams.add(RESTConstants.QUERY_PARAM_LINE_COUNT, "" + messageCount);
+ if(!diskName.equals(CoreConstants.ALL)) {
+ queryParams.add(RESTConstants.QUERY_PARAM_DISK_NAME, diskName);
+ }
+
+ if (!severity.equals(CoreConstants.ALL)) {
+ queryParams.add(RESTConstants.QUERY_PARAM_LOG_SEVERITY, severity);
+ }
+
+ if (fromTimestamp != null) {
+ queryParams.add(RESTConstants.QUERY_PARAM_FROM_TIMESTAMP,
+ DateUtil.dateToString(fromTimestamp, CoreConstants.DATE_WITH_TIME_FORMAT));
+ }
+
+ if (toTimestamp != null) {
+ queryParams.add(RESTConstants.QUERY_PARAM_TO_TIMESTAMP,
+ DateUtil.dateToString(toTimestamp, CoreConstants.DATE_WITH_TIME_FORMAT));
+ }
+ return queryParams;
}
public static void main(String[] args) {
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java
index 177334bd..8a1e1f37 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/CoreConstants.java
@@ -26,4 +26,8 @@ public class CoreConstants {
public static final String NEWLINE = System.getProperty("line.separator");
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
public static final String ENCODING_UTF8 = "UTF-8";
+ public static final String ALL = "ALL";
+ public static final String DATE_WITH_TIME_FORMAT = "MM/dd/yyyy HH:mm:ss";
+ public static final String PURE_DATE_FORMAT = "MM/dd/yyyy";
+ public static final String PURE_TIME_FORMAT = "HH:mm:ss.SSS";
}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java
new file mode 100644
index 00000000..064037ec
--- /dev/null
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Gluster, Inc. <http://www.gluster.com>
+ * This file is part of Gluster Management Console.
+ *
+ * Gluster Management Console is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Gluster Management Console 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 Affero General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *******************************************************************************/
+package com.gluster.storage.management.core.constants;
+
+import java.util.List;
+
+import com.gluster.storage.management.core.utils.StringUtil;
+
+/**
+ *
+ */
+public class GlusterConstants {
+ public enum VOLUME_LOG_LEVELS {
+ EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG, TRACE
+ };
+
+ public static final List<String> VOLUME_LOG_LEVELS_ARR = StringUtil.enumToArray(VOLUME_LOG_LEVELS.values());
+
+}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java
index 4bd0d292..159c408e 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/RESTConstants.java
@@ -46,6 +46,9 @@ public class RESTConstants {
public static final String QUERY_PARAM_LINE_COUNT = "lineCount";
public static final String QUERY_PARAM_VOLUME_NAME = "volumeName";
public static final String QUERY_PARAM_DELETE_OPTION = "deleteOption";
+ public static final String QUERY_PARAM_LOG_SEVERITY = "severity";
+ public static final String QUERY_PARAM_FROM_TIMESTAMP = "fromTimestamp";
+ public static final String QUERY_PARAM_TO_TIMESTAMP = "toTimestamp";
// Running tasks resource
public static final String RESOURCE_PATH_RUNNING_TASKS = "/cluster/runningtasks";
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/adapters/VolumeLogDateAdapter.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/adapters/VolumeLogDateAdapter.java
index 254d5efd..fac208ad 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/adapters/VolumeLogDateAdapter.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/model/adapters/VolumeLogDateAdapter.java
@@ -19,35 +19,35 @@
package com.gluster.storage.management.core.model.adapters;
-import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
+import com.gluster.storage.management.core.utils.DateUtil;
+
/**
* Adapter class used for converting timestamp from Gluster volume log files to Date object.
*/
public class VolumeLogDateAdapter extends XmlAdapter<String, Date> {
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
- private SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
/* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal(java.lang.Object)
*/
@Override
- public Date unmarshal(String input) throws Exception {
+ public Date unmarshal(String input) {
input = input.trim();
if(input.length() > DATE_FORMAT.length()) {
input = input.substring(0, DATE_FORMAT.length());
}
- return dateFormatter.parse(input);
+ return DateUtil.stringToDate(input, DATE_FORMAT);
}
/* (non-Javadoc)
* @see javax.xml.bind.annotation.adapters.XmlAdapter#marshal(java.lang.Object)
*/
@Override
- public String marshal(Date input) throws Exception {
- return dateFormatter.format(input);
+ public String marshal(Date input) {
+ return DateUtil.dateToString(input, DATE_FORMAT);
}
}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java
index d4529a00..8677fecd 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/DateUtil.java
@@ -18,18 +18,94 @@
*******************************************************************************/
package com.gluster.storage.management.core.utils;
-import java.text.DateFormat;
+import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
+import com.gluster.storage.management.core.constants.CoreConstants;
+import com.gluster.storage.management.core.exceptions.GlusterRuntimeException;
+
public class DateUtil {
+
+ /**
+ * Formats given date in pure date format (without time component) using default format
+ * {@link CoreConstants#PURE_DATE_FORMAT}
+ *
+ * @param inputDate
+ * Date to be formatted
+ * @return Formatted String representation of the given date
+ */
public static final String formatDate(Date inputDate) {
- DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
- return formatter.format(inputDate);
+ return dateToString(inputDate, CoreConstants.PURE_DATE_FORMAT);
}
-
+
+ /**
+ * Formats given date in pure time format (without date component) using default format
+ * {@link CoreConstants#PURE_TIME_FORMAT}
+ *
+ * @param inputDate
+ * Date to be formatted
+ * @return Formatted String representation of the given date
+ */
public static final String formatTime(Date inputDate) {
- DateFormat formatter = new SimpleDateFormat("HH:mm:ss.SSS");
- return formatter.format(inputDate);
+ return dateToString(inputDate, CoreConstants.PURE_TIME_FORMAT);
+ }
+
+ /**
+ * Converts given date object to string by formatting it in given format
+ *
+ * @param date
+ * Date to be formatted
+ * @param dateFormat
+ * Date format
+ * @return String representation of the given Date
+ */
+ public static final String dateToString(Date date, String dateFormat) {
+ SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
+ return dateFormatter.format(date);
+ }
+
+ /**
+ * Converts given date object to string by formatting it using default date format
+ * {@link CoreConstants#DATE_WITH_TIME_FORMAT}
+ *
+ * @param date
+ * Date to be formatted
+ * @param dateFormat
+ * Date format
+ * @return String representation of the given Date
+ */
+ public static final String dateToString(Date date) {
+ return dateToString(date, CoreConstants.DATE_WITH_TIME_FORMAT);
+ }
+
+ /**
+ * Converts given string to date using the given date format
+ *
+ * @param input
+ * Input string
+ * @param dateFormat
+ * The date format to be used
+ * @return Date object
+ */
+ public static final Date stringToDate(String input, String dateFormat) {
+ try {
+ SimpleDateFormat dateFormatter = new SimpleDateFormat(dateFormat);
+ return dateFormatter.parse(input);
+ } catch (ParseException e) {
+ throw new GlusterRuntimeException("Error trying to parse string [" + input + "] in to date using format ["
+ + dateFormat + "]", e);
+ }
+ }
+
+ /**
+ * Converts given string to date using the default date format {@link CoreConstants#DATE_WITH_TIME_FORMAT}
+ *
+ * @param input
+ * Input string
+ * @return Date object
+ */
+ public static final Date stringToDate(String input) {
+ return stringToDate(input, CoreConstants.DATE_WITH_TIME_FORMAT);
}
}
diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java
index 8dc5837d..29026410 100644
--- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java
+++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/StringUtil.java
@@ -18,6 +18,7 @@
*******************************************************************************/
package com.gluster.storage.management.core.utils;
+import java.util.ArrayList;
import java.util.List;
public class StringUtil {
@@ -38,4 +39,12 @@ public class StringUtil {
String outputStr = output.toString();
return outputStr.substring(0, outputStr.length() - (delimiter.length()+1));
}
+
+ public static <T extends Enum<T>> List<String> enumToArray(T[] values) {
+ List<String> enumAsArray = new ArrayList<String>();
+ for(T value : values) {
+ enumAsArray.add(value.toString());
+ }
+ return enumAsArray;
+ }
}
diff --git a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java
index 80fd092d..df9f8533 100644
--- a/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java
+++ b/src/com.gluster.storage.management.gui/src/com/gluster/storage/management/gui/views/details/VolumeLogsPage.java
@@ -18,6 +18,8 @@
*******************************************************************************/
package com.gluster.storage.management.gui.views.details;
+import java.util.Calendar;
+import java.util.Date;
import java.util.List;
import org.eclipse.jface.dialogs.MessageDialog;
@@ -46,6 +48,9 @@ import org.eclipse.ui.forms.widgets.FormToolkit;
import com.gluster.storage.management.client.GlusterDataModelManager;
import com.gluster.storage.management.client.VolumesClient;
+import com.gluster.storage.management.core.constants.CoreConstants;
+import com.gluster.storage.management.core.constants.GlusterConstants;
+import com.gluster.storage.management.core.constants.GlusterConstants.VOLUME_LOG_LEVELS;
import com.gluster.storage.management.core.model.LogMessage;
import com.gluster.storage.management.core.model.Status;
import com.gluster.storage.management.core.model.Volume;
@@ -67,6 +72,14 @@ public class VolumeLogsPage extends Composite {
private static final String[] LOG_TABLE_COLUMN_NAMES = new String[] { "Date", "Time", "Disk", "Severity", "Message" };
private TableViewer tableViewer;
+ private Combo disksCombo;
+ private Combo severityCombo;
+ private DateTime fromDate;
+ private DateTime fromTime;
+ private DateTime toDate;
+ private DateTime toTime;
+ private Button fromCheckbox;
+ private Button toCheckbox;
/**
* Create the volume logs page
@@ -103,10 +116,12 @@ public class VolumeLogsPage extends Composite {
createFromDateLabel(composite);
createFromDateField(composite);
createFromTimeField(composite);
+ createFromCheckbox(composite);
createToDateLabel(composite);
createToDateField(composite);
createToTimeField(composite);
+ createToCheckbox(composite);
createSearchButton(composite);
@@ -146,12 +161,29 @@ public class VolumeLogsPage extends Composite {
private void createSearchButton(Composite composite) {
Button btnGo = toolkit.createButton(composite, "&Go", SWT.NONE);
- btnGo.setBounds(605, 55, 60, 30);
+ btnGo.setBounds(615, 55, 50, 30);
btnGo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
VolumesClient client = new VolumesClient(GlusterDataModelManager.getInstance().getSecurityToken());
- LogMessageListResponse response = client.getLogs(volume.getName(), Integer.parseInt(lineCountText.getText()));
+
+ Date fromTimestamp = null;
+ Date toTimestamp = null;
+
+ if(fromCheckbox.getSelection()) {
+ fromTimestamp = extractTimestamp(fromDate, fromTime);
+ }
+
+ if(toCheckbox.getSelection()) {
+ toTimestamp = extractTimestamp(toDate, toTime);
+ }
+
+ if (!validateTimeRange(fromTimestamp, toTimestamp)) {
+ return;
+ }
+
+ LogMessageListResponse response = client.getLogs(volume.getName(), disksCombo.getText(),
+ severityCombo.getText(), fromTimestamp, toTimestamp, Integer.parseInt(lineCountText.getText()));
Status status = response.getStatus();
if(status.isSuccess()) {
List<LogMessage> logMessages = response.getLogMessages();
@@ -165,51 +197,120 @@ public class VolumeLogsPage extends Composite {
});
}
+ protected boolean validateTimeRange(Date fromTimestamp, Date toTimestamp) {
+ if(fromTimestamp == null && toTimestamp == null) {
+ // no time range selected. nothing to validate.
+ return true;
+ }
+
+ Calendar calendar = Calendar.getInstance();
+ Date now = calendar.getTime();
+ if(fromTimestamp != null && fromTimestamp.after(now)) {
+ MessageDialog.openError(getShell(), "Volume Logs", "From time can't be greater than current time!");
+ return false;
+ }
+
+ if(toTimestamp != null) {
+ if (toTimestamp.after(now)) {
+ MessageDialog.openError(getShell(), "Volume Logs", "To time can't be greater than current time!");
+ return false;
+ }
+
+ if(fromTimestamp.after(toTimestamp)) {
+ MessageDialog.openError(getShell(), "Volume Logs", "From time can't be greater than To time!");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void createToCheckbox(Composite composite) {
+ toCheckbox = toolkit.createButton(composite, null, SWT.CHECK);
+ toCheckbox.setBounds(320, 60, 15, 20);
+ toCheckbox.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (toCheckbox.getSelection()) {
+ toDate.setEnabled(true);
+ toTime.setEnabled(true);
+ } else {
+ toDate.setEnabled(false);
+ toTime.setEnabled(false);
+ }
+ }
+ });
+ }
+
private void createToTimeField(Composite composite) {
- DateTime toTime = new DateTime(composite, SWT.BORDER | SWT.TIME);
- toTime.setBounds(480, 60, 120, 20);
+ toTime = new DateTime(composite, SWT.BORDER | SWT.TIME);
+ toTime.setBounds(490, 60, 120, 20);
+ toTime.setEnabled(false);
toolkit.adapt(toTime);
toolkit.paintBordersFor(toTime);
}
private void createToDateField(Composite composite) {
- DateTime toDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
- toDate.setBounds(355, 60, 120, 20);
+ toDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
+ toDate.setBounds(365, 60, 120, 20);
+ toDate.setEnabled(false);
toolkit.adapt(toDate);
toolkit.paintBordersFor(toDate);
}
private void createToDateLabel(Composite composite) {
Label lblTo = toolkit.createLabel(composite, "To", SWT.NONE);
- lblTo.setBounds(329, 60, 26, 20);
+ lblTo.setBounds(340, 60, 25, 20);
+ }
+
+ private void createFromCheckbox(Composite composite) {
+ fromCheckbox = toolkit.createButton(composite, null, SWT.CHECK);
+ fromCheckbox.setBounds(0, 60, 15, 20);
+ fromCheckbox.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (fromCheckbox.getSelection()) {
+ fromDate.setEnabled(true);
+ fromTime.setEnabled(true);
+ } else {
+ fromDate.setEnabled(false);
+ fromTime.setEnabled(false);
+ }
+ }
+ });
}
private void createFromTimeField(Composite composite) {
- DateTime fromTime = new DateTime(composite, SWT.BORDER | SWT.TIME);
- fromTime.setBounds(171, 60, 120, 20);
+ fromTime = new DateTime(composite, SWT.BORDER | SWT.TIME);
+ fromTime.setBounds(190, 60, 120, 20);
+ fromTime.setEnabled(false);
toolkit.adapt(fromTime);
toolkit.paintBordersFor(fromTime);
}
private void createFromDateField(Composite composite) {
- DateTime fromDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
- fromDate.setBounds(45, 60, 120, 20);
+ fromDate = new DateTime(composite, SWT.BORDER | SWT.DROP_DOWN);
+ fromDate.setBounds(60, 60, 120, 20);
+ fromDate.setEnabled(false);
toolkit.adapt(fromDate);
toolkit.paintBordersFor(fromDate);
}
private void createFromDateLabel(Composite composite) {
Label lblFrom = toolkit.createLabel(composite, "from", SWT.NONE);
- lblFrom.setBounds(0, 60, 40, 20);
+ lblFrom.setBounds(20, 60, 40, 20);
}
private void createSeverityCombo(Composite composite) {
- Combo severityCombo = new Combo(composite, SWT.NONE);
+ severityCombo = new Combo(composite, SWT.READ_ONLY);
severityCombo.setBounds(555, 15, 110, 20);
- severityCombo.setItems(new String[] {"ALL", "SEVERE", "WARNING", "DEBUG", "INFO"});
+
+ severityCombo.setItems(GlusterConstants.VOLUME_LOG_LEVELS_ARR.toArray(new String[0]));
+ severityCombo.select(VOLUME_LOG_LEVELS.ERROR.ordinal());
+ severityCombo.add(CoreConstants.ALL, 0);
+
toolkit.adapt(severityCombo);
toolkit.paintBordersFor(severityCombo);
- severityCombo.select(1);
}
private void createSeverityLabel(Composite composite) {
@@ -218,9 +319,10 @@ public class VolumeLogsPage extends Composite {
}
private void createDisksCombo(Composite composite) {
- Combo disksCombo = new Combo(composite, SWT.NONE);
+ disksCombo = new Combo(composite, SWT.READ_ONLY);
disksCombo.setBounds(365, 15, 100, 20);
- disksCombo.setItems(new String[] {"ALL", "sda", "sdb", "sdc", "sdd"});
+ disksCombo.setItems(volume.getDisks().toArray(new String[0]));
+ disksCombo.add(CoreConstants.ALL, 0);
toolkit.adapt(disksCombo);
toolkit.paintBordersFor(disksCombo);
disksCombo.select(0);
@@ -288,4 +390,17 @@ public class VolumeLogsPage extends Composite {
TableColumnLayout tableColumnLayout = (TableColumnLayout) table.getParent().getLayout();
tableColumnLayout.setColumnData(column, new ColumnWeightData(weight));
}
+
+ private Date extractTimestamp(DateTime date, DateTime time) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setLenient(false);
+ calendar.set(Calendar.DAY_OF_MONTH, date.getDay());
+ // in Calendar class, month starts with zero i.e. Jan = 0
+ calendar.set(Calendar.MONTH, date.getMonth());
+ calendar.set(Calendar.YEAR, date.getYear());
+ calendar.set(Calendar.HOUR_OF_DAY, time.getHours());
+ calendar.set(Calendar.MINUTE, time.getMinutes());
+ calendar.set(Calendar.SECOND, time.getSeconds());
+ return calendar.getTime();
+ }
}
diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java
index 457776cc..313a58b2 100644
--- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java
+++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/VolumesResource.java
@@ -27,7 +27,10 @@ import static com.gluster.storage.management.core.constants.RESTConstants.PATH_P
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DELETE_OPTION;
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DISKS;
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_DISK_NAME;
+import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_FROM_TIMESTAMP;
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LINE_COUNT;
+import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_LOG_SEVERITY;
+import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TO_TIMESTAMP;
import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_VOLUME_NAME;
import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_VOLUMES;
import static com.gluster.storage.management.core.constants.RESTConstants.SUBRESOURCE_DEFAULT_OPTIONS;
@@ -37,6 +40,9 @@ import static com.gluster.storage.management.core.constants.RESTConstants.SUBRES
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
import java.util.List;
import javax.ws.rs.Consumes;
@@ -62,6 +68,7 @@ import com.gluster.storage.management.core.response.GenericResponse;
import com.gluster.storage.management.core.response.LogMessageListResponse;
import com.gluster.storage.management.core.response.VolumeListResponse;
import com.gluster.storage.management.core.response.VolumeOptionInfoListResponse;
+import com.gluster.storage.management.core.utils.DateUtil;
import com.gluster.storage.management.server.constants.VolumeOptionsDefaults;
import com.gluster.storage.management.server.utils.GlusterUtil;
import com.gluster.storage.management.server.utils.ServerUtil;
@@ -280,10 +287,18 @@ public class VolumesResource {
String logFilePath = logDir + CoreConstants.FILE_SEPARATOR + logFileName;
// Usage: get_volume_disk_log.py <volumeName> <diskName> <lineCount>
- LogMessageListResponse response = ((LogMessageListResponse) serverUtil.executeOnServer(true, serverName, VOLUME_BRICK_LOG_SCRIPT
- + " " + logFilePath + " " + lineCount, LogMessageListResponse.class));
- Status status = response.getStatus();
- if (!response.getStatus().isSuccess()) {
+ Object responseObj = serverUtil.executeOnServer(true, serverName, VOLUME_BRICK_LOG_SCRIPT
+ + " " + logFilePath + " " + lineCount, LogMessageListResponse.class);
+ Status status = null;
+ LogMessageListResponse response = null;
+ if(responseObj instanceof LogMessageListResponse) {
+ response = (LogMessageListResponse)responseObj;
+ status = response.getStatus();
+ } else {
+ status = (Status)responseObj;
+ }
+
+ if (!status.isSuccess()) {
throw new GlusterRuntimeException(status.toString());
}
@@ -300,17 +315,16 @@ public class VolumesResource {
@GET
@Path("{" + PATH_PARAM_VOLUME_NAME + "}/" + SUBRESOURCE_LOGS)
public LogMessageListResponse getLogs(@PathParam(PATH_PARAM_VOLUME_NAME) String volumeName,
- @QueryParam(QUERY_PARAM_DISK_NAME) String diskName, @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount) {
+ @QueryParam(QUERY_PARAM_DISK_NAME) String diskName, @QueryParam(QUERY_PARAM_LOG_SEVERITY) String severity,
+ @QueryParam(QUERY_PARAM_FROM_TIMESTAMP) String fromTimestamp,
+ @QueryParam(QUERY_PARAM_TO_TIMESTAMP) String toTimestamp,
+ @QueryParam(QUERY_PARAM_LINE_COUNT) Integer lineCount) {
List<LogMessage> logMessages = null;
try {
Volume volume = getVolume(volumeName);
if (diskName == null || diskName.isEmpty()) {
- logMessages = new ArrayList<LogMessage>();
- // fetch logs for every brick of the volume
- for (String brick : volume.getBricks()) {
- logMessages.addAll(getBrickLogs(volume, brick, lineCount));
- }
+ logMessages = getLogsForAllBricks(volume, lineCount);
} else {
// fetch logs for given brick of the volume
logMessages = getBrickLogs(volume, getBrickForDisk(volume, diskName), lineCount);
@@ -318,9 +332,70 @@ public class VolumesResource {
} catch (Exception e) {
return new LogMessageListResponse(new Status(e), null);
}
-
+
+ filterLogsBySeverity(logMessages, severity);
+ filterLogsByTime(logMessages, fromTimestamp, toTimestamp);
return new LogMessageListResponse(Status.STATUS_SUCCESS, logMessages);
}
+
+ private void filterLogsByTime(List<LogMessage> logMessages, String fromTimestamp, String toTimestamp) {
+ Date fromTime = null, toTime = null;
+
+ if(fromTimestamp != null && !fromTimestamp.isEmpty()) {
+ fromTime = DateUtil.stringToDate(fromTimestamp);
+ }
+
+ if(toTimestamp != null && !toTimestamp.isEmpty()) {
+ toTime = DateUtil.stringToDate(toTimestamp);
+ }
+
+ List<LogMessage> messagesToRemove = new ArrayList<LogMessage>();
+ for(LogMessage logMessage : logMessages) {
+ Date logTimestamp = logMessage.getTimestamp();
+ if(fromTime != null && logTimestamp.before(fromTime)) {
+ messagesToRemove.add(logMessage);
+ continue;
+ }
+
+ if(toTime != null && logTimestamp.after(toTime)) {
+ messagesToRemove.add(logMessage);
+ }
+ }
+ logMessages.removeAll(messagesToRemove);
+ }
+
+ private void filterLogsBySeverity(List<LogMessage> logMessages, String severity) {
+ if(severity == null || severity.isEmpty()) {
+ return;
+ }
+
+ List<LogMessage> messagesToRemove = new ArrayList<LogMessage>();
+ for(LogMessage logMessage : logMessages) {
+ if(!logMessage.getSeverity().equals(severity)) {
+ messagesToRemove.add(logMessage);
+ }
+ }
+ logMessages.removeAll(messagesToRemove);
+ }
+
+ private List<LogMessage> getLogsForAllBricks(Volume volume, Integer lineCount) {
+ List<LogMessage> logMessages;
+ logMessages = new ArrayList<LogMessage>();
+ // fetch logs for every brick of the volume
+ for (String brick : volume.getBricks()) {
+ logMessages.addAll(getBrickLogs(volume, brick, lineCount));
+ }
+
+ // Sort the log messages based on log timestamp
+ Collections.sort(logMessages, new Comparator<LogMessage>() {
+ @Override
+ public int compare(LogMessage message1, LogMessage message2) {
+ return message1.getTimestamp().compareTo(message2.getTimestamp());
+ }
+ });
+
+ return logMessages;
+ }
@POST
@Path("{" + QUERY_PARAM_VOLUME_NAME + "}/" + SUBRESOURCE_DISKS)