Home » Eclipse Projects » Eclipse Scout » Server/Ui-Session List and the Upcoming Release
Server/Ui-Session List and the Upcoming Release [message #1863649] |
Mon, 19 February 2024 03:50  |
Eclipse User |
|
|
|
Hi there,
I am looking forward to the upcoming release and the docker build.
Currently we are using tomcat based docker images and include the war file (server and ui combined) and the tomcat manager application. We use the manager application to monitor the active sessions of the applications. Some time ago I wondered if we could use Jetty instead, but I found out that Jetty does not provide a list of sessions since at least version 9.4 (https://stackoverflow.com/questions/54398968/embedded-jetty-display-all-sessions-in-context).
I know there is an org.eclipse.scout.rt.server.admin.html.view.SessionsView, but the list of sessions is always empty, both in dev mode with Jetty and in production with tomcat. Am I missing a setting to enable session tracking in scout or is there another way to get the list of sessions since with the new release and the docker build I can't use the manager application anymore?
Thanks.
Nils
|
|
| |
Re: Server/Ui-Session List and the Upcoming Release [message #1863653 is a reply to message #1863650] |
Mon, 19 February 2024 05:36   |
Eclipse User |
|
|
|
Hi Matthias,
Thanks for your quick reply. And you are right, in the contacts application I can also see the sessions. That is when I start server.app.dev and ui.html.app.dev. When I start all.app.dev, I don't even have the servlet responding to /process.
Of course, we don't need it when using the org.eclipse.scout.rt.serverbridge. That it is present in our applications is because I kept it in the web.xml.
Is it still correct that when using client and server, there are always 2 sessions for a client, 1 client session and 1 server session, as mentioned in this post?
When using the server bridge, there is only 1 session, the client session that is not listed in the /process session list and if I want to have such a list, I have to implement something similar for the client session?
Best regards
Nils
[Updated on: Mon, 19 February 2024 07:41] by Moderator
|
|
| |
Re: Server/Ui-Session List and the Upcoming Release [message #1863724 is a reply to message #1863709] |
Fri, 23 February 2024 06:19   |
Eclipse User |
|
|
|
Hi there,
just for the sake of completeness, Scout offers further monitoring possibilities:
MBeans
There are some @MXBean available providing information about the number of sessions (http, ui, client server) and a few other metrics.
You can use jconsole, that is included in the JDK, to show that information.

Open Telemetry
Recently we have added basic support for Open Telemetry. To enable it, please follow the steps described in the Observability chapter. You can then use tools like Grafana to monitor your app.
Attachment: jconsole.png
(Size: 53.07KB, Downloaded 266 times)
[Updated on: Fri, 23 February 2024 15:57] by Moderator
|
|
| | | | |
Re: Server/Ui-Session List and the Upcoming Release [message #1864485 is a reply to message #1864002] |
Tue, 19 March 2024 09:36  |
Eclipse User |
|
|
|
Hello Bruno,
yes, but I also looked into the MBeans mentioned by Claudio and the session registry suggested by Beat.
Now I have a service running in the client module that provides tabular data, with the necessary information and the ability to terminate a session. I have tried to integrate the 'scout.diagnostics.httpSessionIdLogMode' setting, but the helper class is in the server module and is not accessible to the service.
@ApplicationScoped
public class SessionManagementService implements IGlobalSessionListener {
private static final Logger LOG = LoggerFactory.getLogger(SessionManagementService.class);
private final MBeanServer mBeanServer;
private final Map<String, WeakReference<ClientSession>> clientSessions;
private final Map<String, WeakReference<ISession>> serverSessions;
public SessionManagementService() {
mBeanServer = ManagementFactory.getPlatformMBeanServer();
clientSessions = new WeakHashMap<>();
serverSessions = new WeakHashMap<>();
}
public SessionTablePageData getSessionTableData() {
if (!ACCESS.check(new ReadSessionPermission())) {
throw new VetoException(TEXTS.get("AuthorizationFailed"));
}
ObjectName sessions = MBeanUtility.toJmxName("org.eclipse.scout.rt.ui.html", "Sessions");
SessionTablePageData sessionTablePageData = new SessionTablePageData();
try {
Object sessionDetails = mBeanServer.getAttribute(sessions, "SessionDetails");
if (sessionDetails instanceof CompositeData[] compositeDataArray) {
var sessionRows = Arrays.stream(compositeDataArray).map(this::createSessionTableRow).toArray(SessionTableRowData[]::new);
sessionTablePageData.setRows(sessionRows);
}
} catch (MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException e) {
LOG.error("Error while querying MBean", e);
throw new VetoException(TEXTS.get("mgmt.sessions.error.mbean", e.getClass().getSimpleName(), e.getMessage()));
}
return sessionTablePageData;
}
private SessionTableRowData createSessionTableRow(CompositeData compositeData) {
var clientSessionId = compositeData.get("clientSessionId") instanceof String clientSessionIdString ? clientSessionIdString : "";
var clientState = compositeData.get("clientState") instanceof String clientStateString ? clientStateString : "";
var userId = compositeData.get("userId") instanceof String userIdString ? userIdString : "";
var ageInSeconds = compositeData.get("ageInSeconds") instanceof Long ageInSecondsLong ? ageInSecondsLong : 0L;
var httpSessionId = compositeData.get("httpSessionId") instanceof String httpSessionIdString ? httpSessionIdString : "";
var lastAccessed = compositeData.get("lastAccessed") instanceof Date lastAccessedLong ? lastAccessedLong : null;
var uiSessionId = compositeData.get("uiSessionId") instanceof String uiSessionIdString ? uiSessionIdString : "";
var uiState = compositeData.get("uiState") instanceof String uiStateString ? uiStateString : "";
SessionTableRowData row = new SessionTableRowData();
row.setClientSessionId(clientSessionId);
row.setClientState(clientState);
row.setUserId(userId);
row.setAgeInSeconds(ageInSeconds);
row.setHttpSessionId(httpSessionId);
row.setLastAccessed(lastAccessed);
row.setUiSessionId(uiSessionId);
row.setUiState(uiState);
var userAgent = findUserAgent(clientSessionId);
row.setUserAgent(userAgent);
return row;
}
private String findUserAgent(String clientSessionId) {
if (clientSessions.containsKey(clientSessionId)) {
var clientSession = clientSessions.get(clientSessionId).get();
if (clientSession != null) {
return clientSession.getUserAgent().toString();
}
}
return "Unknown";
}
public void terminateSession(String clientSessionId) {
if (!ACCESS.check(new DeleteSessionPermission())) {
throw new VetoException(TEXTS.get("AuthorizationFailed"));
}
if (clientSessionId == null || clientSessionId.isBlank()) {
return;
}
var clientSessionWeakReference = clientSessions.get(clientSessionId);
if (clientSessionWeakReference == null) {
return;
}
IClientSession clientSession = clientSessionWeakReference.get();
if (clientSession == null) {
return;
}
BEANS.get(ClientSessionStopHelper.class).scheduleStop(clientSession, true, "Kicked by admin.");
}
protected void registerClientSession(ClientSession session) {
clientSessions.put(session.getId(), new WeakReference<>(session));
}
protected void unregisterClientSession(ClientSession session) {
clientSessions.remove(session.getId());
}
protected void registerServerSession(ISession session) {
serverSessions.put(session.getId(), new WeakReference<>(session));
}
protected void unregisterServerSession(ISession session) {
serverSessions.remove(session.getId());
}
@Override
public void sessionChanged(SessionEvent event) {
if (event.getSource() instanceof ClientSession clientSession) {
if (event.getType() == SessionEvent.TYPE_STARTED) {
registerClientSession(clientSession);
}
if (event.getType() == SessionEvent.TYPE_STOPPED) {
unregisterClientSession(clientSession);
}
} else if (!(event instanceof IClientSession) && event.getSource() != null) {
var serverSession = event.getSource();
if (event.getType() == SessionEvent.TYPE_STARTED) {
registerServerSession(serverSession);
}
if (event.getType() == SessionEvent.TYPE_STOPPED) {
unregisterServerSession(serverSession);
}
}
}
}
With the metrics, I copied the logged metrics from the OtlpJsonLoggingMetricExporter. ChatGPT can help with the "aggregated summary", e.g. by asking:
Quote:
Please create a human readable yaml file with a summary of the attached json metrics file.
The summary should contain 2 blocks, the resource_attributes and the scopes. The scopes block should contain a block for each scope, which should contain a list of metrics within the scope. Use the canonical path of the metric as the key and a list of the names of the underlying attributes. Please omit the actual metric values and time and only specify the data type of the value. Add the description and the unit of the metric, if available. If there are only 10 or fewer possible values for an attribute, please list them as 1 string, divided by the pipe symbol. You can shorten the output for the standard scope: "io.opentelemetry.runtime-telemetry-java8".
The output varies depending on the mood of the chatbot, it seems. Sometimes it works, sometimes it doesn't
|
|
|
Goto Forum:
Current Time: Thu Jun 19 10:02:25 EDT 2025
Powered by FUDForum. Page generated in 0.25337 seconds
|