diff options
| author | Shireesh Anjal <shireesh@gluster.com> | 2011-04-26 20:09:44 +0530 |
|---|---|---|
| committer | Shireesh Anjal <shireesh@gluster.com> | 2011-04-30 22:40:53 +0530 |
| commit | ffcf099e6186502e750676b9b266963d23c62756 (patch) | |
| tree | 1799489d61e49fa4b860fa57bdbc077094c45db7 /src | |
| parent | 9c749f036a5f6efd83b3d5fd8e90681916448db4 (diff) | |
Story#34 - Volume logs
Diffstat (limited to 'src')
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) |
