mirror of
https://gitee.com/jmix/cuba.git
synced 2024-12-04 12:17:41 +08:00
"Server log" - "download" implementation obligates to register LogDownloadController in every web context #PL-4320
This commit is contained in:
parent
ded8fce8c3
commit
a131009d3f
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2015 Haulmont. All rights reserved.
|
||||
* Use is subject to license terms, see http://www.cuba-platform.com/license for details.
|
||||
*/
|
||||
|
||||
package com.haulmont.cuba.web.app.ui.serverlogviewer;
|
||||
|
||||
import com.haulmont.cuba.core.entity.JmxInstance;
|
||||
import com.haulmont.cuba.core.sys.logging.LogArchiver;
|
||||
import com.haulmont.cuba.gui.AppConfig;
|
||||
import com.haulmont.cuba.gui.WindowParam;
|
||||
import com.haulmont.cuba.gui.components.*;
|
||||
import com.haulmont.cuba.web.export.LogDataProvider;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author artamonov
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LogDownloadOptionsWindow extends AbstractWindow {
|
||||
|
||||
private static final int BYTES_IN_MB = 1024 * 1024;
|
||||
|
||||
@Inject
|
||||
protected Button downloadFullBtn;
|
||||
|
||||
@Inject
|
||||
protected Button downloadTailBtn;
|
||||
|
||||
@Inject
|
||||
protected LookupField remoteContextField;
|
||||
|
||||
@Inject
|
||||
protected BoxLayout remoteContextBox;
|
||||
|
||||
@Inject
|
||||
protected Label sizeNotificationLabel;
|
||||
|
||||
@WindowParam(required = true)
|
||||
protected JmxInstance connection;
|
||||
|
||||
@WindowParam(required = true)
|
||||
protected String logFileName;
|
||||
|
||||
@WindowParam
|
||||
protected List<String> remoteContextList;
|
||||
|
||||
@WindowParam(required = true)
|
||||
protected Long logFileSize;
|
||||
|
||||
@Override
|
||||
public void init(Map<String, Object> params) {
|
||||
super.init(params);
|
||||
|
||||
getDialogParams().setWidthAuto();
|
||||
|
||||
if (remoteContextList == null || remoteContextList.isEmpty()) {
|
||||
remoteContextBox.setVisible(false);
|
||||
} else {
|
||||
List<String> contexts = new ArrayList<>(remoteContextList);
|
||||
Collections.sort(contexts, new Comparator<String>() {
|
||||
@Override
|
||||
public int compare(String o1, String o2) {
|
||||
if ((o1.contains("core") && !o2.contains("core"))
|
||||
|| (o2.contains("portal") && !o1.contains("portal"))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((o2.contains("core") && !o1.contains("core"))
|
||||
|| (o1.contains("portal") && !o2.contains("portal"))) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return o1.compareTo(o2);
|
||||
}
|
||||
});
|
||||
remoteContextField.setOptionsList(contexts);
|
||||
remoteContextField.setValue(contexts.get(0));
|
||||
}
|
||||
|
||||
if (logFileSize <= LogArchiver.LOG_TAIL_FOR_PACKING_SIZE) {
|
||||
downloadTailBtn.setVisible(false);
|
||||
downloadFullBtn.setCaption(getMessage("log.download"));
|
||||
} else {
|
||||
long sizeMb = logFileSize / BYTES_IN_MB;
|
||||
|
||||
sizeNotificationLabel.setValue(formatMessage("log.selectDownloadOption", sizeMb));
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
close(CLOSE_ACTION_ID);
|
||||
}
|
||||
|
||||
public void downloadTail() {
|
||||
LogDataProvider logDataProvider;
|
||||
if (remoteContextBox.isVisible()) {
|
||||
logDataProvider = new LogDataProvider(connection, logFileName,
|
||||
(String) remoteContextField.getValue(), true);
|
||||
} else {
|
||||
logDataProvider = new LogDataProvider(connection, logFileName, true);
|
||||
}
|
||||
|
||||
exportFile(logDataProvider, logFileName);
|
||||
|
||||
close(CLOSE_ACTION_ID);
|
||||
}
|
||||
|
||||
public void downloadFull() {
|
||||
LogDataProvider logDataProvider;
|
||||
if (remoteContextBox.isVisible()) {
|
||||
logDataProvider = new LogDataProvider(connection, logFileName,
|
||||
(String) remoteContextField.getValue(), true);
|
||||
} else {
|
||||
logDataProvider = new LogDataProvider(connection, logFileName, true);
|
||||
}
|
||||
|
||||
exportFile(logDataProvider, logFileName);
|
||||
|
||||
close(CLOSE_ACTION_ID);
|
||||
}
|
||||
|
||||
protected void exportFile(LogDataProvider logDataProvider, String fileName) {
|
||||
AppConfig.createExportDisplay(this).show(logDataProvider, fileName + ".zip");
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@
|
||||
|
||||
package com.haulmont.cuba.web.app.ui.serverlogviewer;
|
||||
|
||||
import com.haulmont.bali.util.ParamsMap;
|
||||
import com.haulmont.cuba.core.entity.JmxInstance;
|
||||
import com.haulmont.cuba.core.global.AppBeans;
|
||||
import com.haulmont.cuba.core.global.UserSessionSource;
|
||||
@ -14,13 +15,10 @@ import com.haulmont.cuba.core.sys.logging.LoggingHelper;
|
||||
import com.haulmont.cuba.gui.AppConfig;
|
||||
import com.haulmont.cuba.gui.WindowManager;
|
||||
import com.haulmont.cuba.gui.components.*;
|
||||
import com.haulmont.cuba.gui.components.Button;
|
||||
import com.haulmont.cuba.gui.components.CheckBox;
|
||||
import com.haulmont.cuba.gui.components.Component;
|
||||
import com.haulmont.cuba.gui.components.Label;
|
||||
import com.haulmont.cuba.gui.components.Timer;
|
||||
import com.haulmont.cuba.gui.data.CollectionDatasource;
|
||||
import com.haulmont.cuba.gui.data.ValueListener;
|
||||
import com.haulmont.cuba.gui.export.ExportDisplay;
|
||||
import com.haulmont.cuba.security.global.UserSession;
|
||||
import com.haulmont.cuba.web.app.ui.jmxinstance.edit.JmxInstanceEditor;
|
||||
import com.haulmont.cuba.web.export.LogDataProvider;
|
||||
@ -31,7 +29,8 @@ import com.haulmont.cuba.web.jmx.JmxRemoteLoggingAPI;
|
||||
import com.vaadin.event.ShortcutAction;
|
||||
import com.vaadin.event.ShortcutListener;
|
||||
import com.vaadin.shared.ui.label.ContentMode;
|
||||
import com.vaadin.ui.*;
|
||||
import com.vaadin.ui.ComboBox;
|
||||
import com.vaadin.ui.Panel;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
@ -53,8 +52,6 @@ public class ServerLogWindow extends AbstractWindow {
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private static final int BYTES_IN_MB = (1024 * 1024);
|
||||
|
||||
@Inject
|
||||
protected CollectionDatasource<JmxInstance, UUID> jmxInstancesDs;
|
||||
|
||||
@ -413,34 +410,22 @@ public class ServerLogWindow extends AbstractWindow {
|
||||
if (fileName != null) {
|
||||
try {
|
||||
final JmxInstance selectedConnection = getSelectedConnection();
|
||||
// check if we have many suitable JmxControlBean instances
|
||||
// show dialog with context select and size options if needed
|
||||
List<String> availableContexts = jmxRemoteLoggingAPI.getAvailableContexts(selectedConnection);
|
||||
|
||||
long size = jmxRemoteLoggingAPI.getLogFileSize(selectedConnection, fileName);
|
||||
|
||||
if (size <= LogArchiver.LOG_TAIL_FOR_PACKING_SIZE) {
|
||||
exportFile(new LogDataProvider(selectedConnection, fileName), fileName);
|
||||
if (size <= LogArchiver.LOG_TAIL_FOR_PACKING_SIZE && availableContexts.size() == 1) {
|
||||
ExportDisplay exportDisplay = AppConfig.createExportDisplay(this);
|
||||
exportDisplay.show(new LogDataProvider(selectedConnection, fileName), fileName + ".zip");
|
||||
} else {
|
||||
long sizeMb = size / BYTES_IN_MB;
|
||||
|
||||
showOptionDialog(getMessage("log.downloadOption"), formatMessage("log.selectDownloadOption", sizeMb),
|
||||
MessageType.CONFIRMATION,
|
||||
new Action[]{
|
||||
new AbstractAction("log.downloadTail") {
|
||||
@Override
|
||||
public void actionPerform(Component component) {
|
||||
exportFile(new LogDataProvider(selectedConnection, fileName), fileName);
|
||||
}
|
||||
},
|
||||
new AbstractAction("log.downloadFull") {
|
||||
@Override
|
||||
public void actionPerform(Component component) {
|
||||
exportFile(new LogDataProvider(selectedConnection, fileName, true), fileName);
|
||||
}
|
||||
},
|
||||
new AbstractAction("actions.Cancel") {
|
||||
@Override
|
||||
public void actionPerform(Component component) {
|
||||
}
|
||||
}
|
||||
});
|
||||
openWindow("serverLogDownloadOptionsDialog",
|
||||
WindowManager.OpenType.DIALOG,
|
||||
ParamsMap.of("logFileName", fileName,
|
||||
"connection", selectedConnection,
|
||||
"logFileSize", size,
|
||||
"remoteContextList", availableContexts));
|
||||
}
|
||||
} catch (RuntimeException | LogControlException e) {
|
||||
showNotification(getMessage("exception.logControl"), NotificationType.ERROR);
|
||||
@ -451,10 +436,6 @@ public class ServerLogWindow extends AbstractWindow {
|
||||
}
|
||||
}
|
||||
|
||||
protected void exportFile(LogDataProvider logDataProvider, String fileName) {
|
||||
AppConfig.createExportDisplay(this).show(logDataProvider, fileName + ".zip");
|
||||
}
|
||||
|
||||
public void updateLogTail(@SuppressWarnings("unused") Timer timer) {
|
||||
updateLogTail(true);
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
<!--
|
||||
~ Copyright (c) 2008-2015 Haulmont. All rights reserved.
|
||||
~ Use is subject to license terms, see http://www.cuba-platform.com/license for details.
|
||||
-->
|
||||
|
||||
<window xmlns="http://schemas.haulmont.com/cuba/5.3/window.xsd"
|
||||
class="com.haulmont.cuba.web.app.ui.serverlogviewer.LogDownloadOptionsWindow"
|
||||
messagesPack="com.haulmont.cuba.web.app.ui.serverlogviewer"
|
||||
caption="msg://log.download.options">
|
||||
<layout spacing="true">
|
||||
<hbox spacing="true" id="remoteContextBox">
|
||||
<label value="msg://log.remoteContext" align="MIDDLE_CENTER"/>
|
||||
<lookupField id="remoteContextField" required="true" width="200px"/>
|
||||
</hbox>
|
||||
|
||||
<label id="sizeNotificationLabel"/>
|
||||
|
||||
<hbox spacing="true" align="MIDDLE_RIGHT">
|
||||
<button id="downloadTailBtn" caption="msg://log.downloadTail" invoke="downloadTail"/>
|
||||
<button id="downloadFullBtn" caption="msg://log.downloadFull" invoke="downloadFull"/>
|
||||
<button caption="msg://actions.Cancel" invoke="cancel" icon="icons/cancel.png"/>
|
||||
</hbox>
|
||||
</layout>
|
||||
</window>
|
@ -26,7 +26,10 @@ log.notSelected=Log file is not selected
|
||||
log.downloadOption=Download log file
|
||||
log.downloadTail=Tail 20 MB
|
||||
log.downloadFull=Full log
|
||||
log.selectDownloadOption=Log file size is %s.\nDo you want do dowload full log?
|
||||
log.download=Download
|
||||
log.download.options=Download log file
|
||||
log.remoteContext=Remote context
|
||||
log.selectDownloadOption=Log file size is %s. Do you want do dowload full log?
|
||||
|
||||
actions.Get=Get
|
||||
actions.Set=Set
|
||||
|
@ -27,7 +27,10 @@ log.notSelected=Файл журнала не выбран
|
||||
log.downloadOption=Скачать файл журнала
|
||||
log.downloadTail=Последние 20 МБ
|
||||
log.downloadFull=Весь файл
|
||||
log.selectDownloadOption=Размер файла журнала %s МБ.\nВы хотите скачать весь файл?
|
||||
log.download.options=Скачать файл журнала
|
||||
log.download=Скачать
|
||||
log.remoteContext=Удалённый контекст
|
||||
log.selectDownloadOption=Размер файла журнала %s МБ. Вы хотите скачать весь файл?
|
||||
|
||||
actions.Get=Прочитать
|
||||
actions.Set=Установить
|
||||
|
@ -53,16 +53,21 @@ public class LogDataProvider implements ExportDataProvider {
|
||||
|
||||
protected JmxInstance jmxInstance;
|
||||
|
||||
protected String remoteContext;
|
||||
protected boolean downloadFullLog = false;
|
||||
|
||||
public LogDataProvider(JmxInstance jmxInstance, String logFileName) {
|
||||
this.logFileName = logFileName;
|
||||
this.jmxInstance = jmxInstance;
|
||||
this(jmxInstance, logFileName, null, false);
|
||||
}
|
||||
|
||||
public LogDataProvider(JmxInstance jmxInstance, String logFileName, boolean downloadFullLog) {
|
||||
this(jmxInstance, logFileName, null, downloadFullLog);
|
||||
}
|
||||
|
||||
public LogDataProvider(JmxInstance jmxInstance, String logFileName, String remoteContext, boolean downloadFullLog) {
|
||||
this.logFileName = logFileName;
|
||||
this.jmxInstance = jmxInstance;
|
||||
this.remoteContext = remoteContext;
|
||||
this.downloadFullLog = downloadFullLog;
|
||||
}
|
||||
|
||||
@ -73,7 +78,7 @@ public class LogDataProvider implements ExportDataProvider {
|
||||
|
||||
String url;
|
||||
try {
|
||||
url = jmxRemoteLoggingAPI.getLogFileLink(jmxInstance, logFileName);
|
||||
url = jmxRemoteLoggingAPI.getLogFileLink(jmxInstance, remoteContext, logFileName);
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to get log file link from JMX interface");
|
||||
|
||||
|
@ -19,6 +19,7 @@ import javax.management.MBeanServerConnection;
|
||||
import javax.management.ObjectName;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Collection;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
@ -57,6 +58,52 @@ public final class JmxConnectionHelper {
|
||||
});
|
||||
}
|
||||
|
||||
protected static ObjectName getObjectName(final MBeanServerConnection connection, final String remoteContext,
|
||||
final Class objectClass) throws IOException {
|
||||
Set<ObjectName> names = connection.queryNames(null, null);
|
||||
return (ObjectName) CollectionUtils.find(names, new Predicate() {
|
||||
@Override
|
||||
public boolean evaluate(Object o) {
|
||||
ObjectName objectName = (ObjectName) o;
|
||||
|
||||
if (StringUtils.equals(remoteContext, objectName.getDomain())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MBeanInfo info;
|
||||
try {
|
||||
info = connection.getMBeanInfo(objectName);
|
||||
} catch (Exception e) {
|
||||
throw new JmxControlException(e);
|
||||
}
|
||||
return StringUtils.equals(objectClass.getName(), info.getClassName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected static Collection<ObjectName> getSuitableObjectNames(final MBeanServerConnection connection,
|
||||
final Class objectClass) throws IOException {
|
||||
Set<ObjectName> names = connection.queryNames(null, null);
|
||||
|
||||
// find all suitable beans
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<ObjectName> suitableNames = CollectionUtils.select(names, new Predicate() {
|
||||
@Override
|
||||
public boolean evaluate(Object o) {
|
||||
ObjectName objectName = (ObjectName) o;
|
||||
MBeanInfo info;
|
||||
try {
|
||||
info = connection.getMBeanInfo(objectName);
|
||||
} catch (Exception e) {
|
||||
throw new JmxControlException(e);
|
||||
}
|
||||
return StringUtils.equals(objectClass.getName(), info.getClassName());
|
||||
}
|
||||
});
|
||||
|
||||
return suitableNames;
|
||||
}
|
||||
|
||||
protected static <T> T getProxy(MBeanServerConnection connection, ObjectName objectName, final Class<T> objectClass) {
|
||||
return JMX.newMBeanProxy(connection, objectName, objectClass, true);
|
||||
}
|
||||
|
@ -46,6 +46,16 @@ public interface JmxRemoteLoggingAPI {
|
||||
*/
|
||||
String getLogFileLink(JmxInstance instance, String fileName) throws LogControlException;
|
||||
|
||||
/**
|
||||
* Get URL for log file downloading.
|
||||
*
|
||||
* @param instance jmx connection
|
||||
* @param remoteContext remote web context
|
||||
* @param fileName name of a log file
|
||||
* @return URL
|
||||
*/
|
||||
String getLogFileLink(JmxInstance instance, String remoteContext, String fileName) throws LogControlException;
|
||||
|
||||
/**
|
||||
* Get size for log file downloading.
|
||||
*
|
||||
@ -121,6 +131,12 @@ public interface JmxRemoteLoggingAPI {
|
||||
*/
|
||||
LoggingHostInfo getHostInfo(JmxInstance instance);
|
||||
|
||||
/**
|
||||
* @param instance jmx connection
|
||||
* @return list of available web contexts on this instance
|
||||
*/
|
||||
List<String> getAvailableContexts(JmxInstance instance);
|
||||
|
||||
public class LoggingHostInfo {
|
||||
private List<String> loggerNames;
|
||||
private List<String> appenders;
|
||||
|
@ -16,6 +16,8 @@ import javax.annotation.ManagedBean;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.ObjectName;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -63,6 +65,18 @@ public class JmxRemoteLoggingBean implements JmxRemoteLoggingAPI {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogFileLink(JmxInstance instance, final String remoteContext,
|
||||
final String fileName) throws LogControlException {
|
||||
return withConnection(instance, new JmxAction<String>() {
|
||||
@Override
|
||||
public String perform(JmxInstance jmx, MBeanServerConnection connection) throws Exception {
|
||||
JmxLogControlMBean logControlMBean = getRemoteLogControl(connection, remoteContext);
|
||||
return logControlMBean.getLogFileLink(fileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLogFileSize(JmxInstance instance, final String fileName) throws LogControlException {
|
||||
return withConnection(instance, new JmxAction<Long>() {
|
||||
@ -192,6 +206,22 @@ public class JmxRemoteLoggingBean implements JmxRemoteLoggingAPI {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAvailableContexts(JmxInstance instance) {
|
||||
return withConnection(instance, new JmxAction<List<String>>() {
|
||||
@Override
|
||||
public List<String> perform(JmxInstance jmx, MBeanServerConnection connection) throws Exception {
|
||||
Collection<ObjectName> objectNames =
|
||||
JmxConnectionHelper.getSuitableObjectNames(connection, JmxLogControl.class);
|
||||
List<String> contexts = new ArrayList<>();
|
||||
for (ObjectName objectName : objectNames) {
|
||||
contexts.add(objectName.getDomain());
|
||||
}
|
||||
return contexts;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected JmxLogControlMBean getRemoteLogControl(MBeanServerConnection connection) {
|
||||
ObjectName objectName;
|
||||
try {
|
||||
@ -206,4 +236,19 @@ public class JmxRemoteLoggingBean implements JmxRemoteLoggingAPI {
|
||||
|
||||
return JmxConnectionHelper.getProxy(connection, objectName, JmxLogControlMBean.class);
|
||||
}
|
||||
|
||||
protected JmxLogControlMBean getRemoteLogControl(MBeanServerConnection connection, String remoteContext) {
|
||||
ObjectName objectName;
|
||||
try {
|
||||
objectName = JmxConnectionHelper.getObjectName(connection, remoteContext, JmxLogControl.class);
|
||||
} catch (IOException e) {
|
||||
throw new JmxControlException(e);
|
||||
}
|
||||
|
||||
if (objectName == null) {
|
||||
throw new JmxControlException("Could not find JmxLogControl implementation");
|
||||
}
|
||||
|
||||
return JmxConnectionHelper.getProxy(connection, objectName, JmxLogControlMBean.class);
|
||||
}
|
||||
}
|
@ -50,6 +50,9 @@
|
||||
<screen id="serverLogLoggerControlDialog"
|
||||
template="/com/haulmont/cuba/web/app/ui/serverlogviewer/control-logger-window.xml" multipleOpen="true"/>
|
||||
|
||||
<screen id="serverLogDownloadOptionsDialog"
|
||||
template="com/haulmont/cuba/web/app/ui/serverlogviewer/log-download-options.xml"/>
|
||||
|
||||
<screen id="printDomain"
|
||||
class="com.haulmont.cuba.web.app.domain.DomainProvider"/>
|
||||
</screen-config>
|
||||
</screen-config>
|
Loading…
Reference in New Issue
Block a user