diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java index 4485b78b9c..dc79a0b3e3 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/AdempiereWebUI.java @@ -24,6 +24,7 @@ import java.util.Properties; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.TimeUnit; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; @@ -44,6 +45,7 @@ import org.adempiere.webui.theme.ITheme; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.BrowserToken; import org.adempiere.webui.util.UserPreference; +import org.compiere.Adempiere; import org.compiere.model.MRole; import org.compiere.model.MSession; import org.compiere.model.MSysConfig; @@ -65,10 +67,14 @@ import org.zkoss.zk.ui.Desktop; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.Session; +import org.zkoss.zk.ui.WebApp; import org.zkoss.zk.ui.event.ClientInfoEvent; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.sys.DesktopCache; +import org.zkoss.zk.ui.sys.SessionCtrl; +import org.zkoss.zk.ui.sys.WebAppCtrl; import org.zkoss.zk.ui.util.Clients; import org.zkoss.zul.Window; @@ -374,20 +380,39 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb */ public void logout() { - Desktop desktop = Executions.getCurrent().getDesktop(); + final Desktop desktop = Executions.getCurrent().getDesktop(); if (desktop.isServerPushEnabled()) desktop.enableServerPush(false); - Session session = logout0(); - + final WebApp wapp = desktop.getWebApp(); + final DesktopCache desktopCache = ((WebAppCtrl) wapp).getDesktopCache(desktop.getSession()); + Adempiere.getThreadPoolExecutor().schedule(() -> { + try { + desktopCache.removeDesktop(desktop); + } catch (Throwable t) { + t.printStackTrace(); + } + }, 5, TimeUnit.SECONDS); + + final Session session = logout0(); + //clear context, invalidate session Env.getCtx().clear(); - session.invalidate(); + destroySession(session); desktop.setAttribute(DESKTOP_SESSION_INVALIDATED_ATTR, Boolean.TRUE); //redirect to login page Executions.sendRedirect("index.zul"); } + + private void destroySession(final Session session) { + try { + ((SessionCtrl)session).onDestroyed(); + } catch (Throwable t) { + t.printStackTrace(); + } + session.invalidate(); + } public void logoutAfterTabDestroyed(){ Desktop desktop = Executions.getCurrent().getDesktop(); @@ -398,7 +423,7 @@ public class AdempiereWebUI extends Window implements EventListener, IWeb //clear context, invalidate session Env.getCtx().clear(); - session.invalidate(); + destroySession(session); } diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/Statistic.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/Statistic.java new file mode 100644 index 0000000000..ee6b29f4b7 --- /dev/null +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/util/Statistic.java @@ -0,0 +1,157 @@ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - hengsin * + **********************************************************************/ +package org.adempiere.webui.util; + +import java.util.List; +import java.util.concurrent.atomic.LongAdder; + +import org.zkoss.zk.au.AuRequest; +import org.zkoss.zk.ui.Desktop; +import org.zkoss.zk.ui.Session; +import org.zkoss.zk.ui.util.Monitor; + +/** + * Adapted from {@link org.zkoss.zk.ui.util.Statistic} + * @author hengsin + * + */ +public class Statistic implements Monitor { + private final long _startTime; + private LongAdder _nsess = new LongAdder(); + private LongAdder _actsess = new LongAdder(); + private LongAdder _ndt = new LongAdder(); + private LongAdder _actdt = new LongAdder(); + private LongAdder _nupd = new LongAdder(); + private LongAdder _actupd = new LongAdder();; + + public Statistic() { + _startTime = System.currentTimeMillis(); + } + + /** Returns when the server (actually, this monitor) started. + */ + public long getStartTime() { + return _startTime; + } + + /** Returns the total number of sessions that have been created + * since the server started. + */ + public long getTotalSessionCount() { + return _nsess.longValue(); + } + + /** Returns the number of active sessions. + */ + public long getActiveSessionCount() { + return _actsess.longValue(); + } + + /** Returns the average number of sessions being created in an hour. + */ + public double getAverageSessionCount() { + return _nsess.longValue() / getEscapedHours(); + } + + /** Returns the total number of desktops that have been created + * since the server started. + */ + public long getTotalDesktopCount() { + return _ndt.longValue(); + } + + /** Returns the number of active desktops. + */ + public long getActiveDesktopCount() { + return _actdt.longValue(); + } + + /** Returns the average number of desktops being created in an hour. + */ + public double getAverageDesktopCount() { + return _ndt.longValue() / getEscapedHours(); + } + + /** Returns the total number of asynchronous updates that have been received + * since the server started. + */ + public long getTotalUpdateCount() { + return _nupd.longValue(); + } + + /** Returns the number of active asynchronous updates. + */ + public long getActiveUpdateCount() { + return _actupd.longValue(); + } + + /** Returns the average number of asynchronous updates being created + * in an hour. + */ + public double getAverageUpdateCount() { + return _nupd.longValue() / getEscapedHours(); + } + + /** Returns how many hours escaped since the server started. + */ + private double getEscapedHours() { + long v = System.currentTimeMillis() - _startTime; + return ((double) v) / 3600000; + } + + //-- Monitor --// + @Override + public void sessionCreated(Session sess) { + _nsess.increment(); + _actsess.increment(); + } + + @Override + public void sessionDestroyed(Session sess) { + _actsess.decrement(); + } + + @Override + public void desktopCreated(Desktop desktop) { + _ndt.increment(); + _actdt.increment(); + } + + @Override + public void desktopDestroyed(Desktop desktop) { + _actdt.decrement(); + } + + @Override + public void beforeUpdate(Desktop desktop, List requests) { + _nupd.increment(); + _actupd.increment(); + } + + @Override + public void afterUpdate(Desktop desktop) { + _actupd.decrement(); + } +} diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java index 585ec4dc73..881272667c 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/window/AboutWindow.java @@ -44,8 +44,10 @@ import org.adempiere.webui.event.DialogEvents; import org.adempiere.webui.factory.ButtonFactory; import org.adempiere.webui.theme.ThemeManager; import org.adempiere.webui.util.FeedbackManager; +import org.adempiere.webui.util.Statistic; import org.adempiere.webui.util.ZKUpdateUtil; import org.compiere.Adempiere; +import org.compiere.model.MRole; import org.compiere.model.MUser; import org.compiere.util.CLogErrorBuffer; import org.compiere.util.CLogMgt; @@ -62,6 +64,7 @@ import org.zkoss.zhtml.Textarea; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.Events; +import org.zkoss.zk.ui.util.Monitor; import org.zkoss.zul.Borderlayout; import org.zkoss.zul.Center; import org.zkoss.zul.Div; @@ -337,7 +340,22 @@ public class AboutWindow extends Window implements EventListener { pre.setParent(div); Text text = new Text(CLogMgt.getInfo(null).toString()); text.setParent(pre); - + + if (Env.getAD_Client_ID(Env.getCtx())==0 && MRole.getDefault().isAccessAdvanced()) { + addCallback(AFTER_PAGE_ATTACHED, t-> { + Monitor monitor = getDesktop().getWebApp().getConfiguration().getMonitor(); + if (monitor != null && monitor instanceof Statistic) { + Statistic stat = (Statistic) monitor; + StringBuilder info = new StringBuilder(text.getValue()); + info.append("\n"); + info.append("Desktop: ").append("#Created=").append(stat.getTotalDesktopCount()).append(" #Active=").append(stat.getActiveDesktopCount()); + info.append("\n"); + info.append("Session: ").append("#Created=").append(stat.getTotalSessionCount()).append(" #Active=").append(stat.getActiveSessionCount()); + text.setValue(info.toString()); + } + }); + } + return tabPanel; } diff --git a/org.adempiere.ui.zk/WEB-INF/zk.xml b/org.adempiere.ui.zk/WEB-INF/zk.xml index 736c91969a..83c156fb94 100644 --- a/org.adempiere.ui.zk/WEB-INF/zk.xml +++ b/org.adempiere.ui.zk/WEB-INF/zk.xml @@ -23,6 +23,11 @@ org.adempiere.webui.util.LogEventInterceptor + + [Optional] Mointor the statistic + org.adempiere.webui.util.Statistic + + 500