Home » Eclipse Projects » Eclipse Scout » Server/Ui-Session List and the Upcoming Release
| |
Re: Server/Ui-Session List and the Upcoming Release [message #1863653 is a reply to message #1863650] |
Mon, 19 February 2024 10:36 |
Nils Israel Messages: 72 Registered: May 2010 |
Member |
|
|
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 12:41] Report message to a moderator
|
|
|
Re: Server/Ui-Session List and the Upcoming Release [message #1863709 is a reply to message #1863653] |
Thu, 22 February 2024 08:34 |
|
Hi Nils
With the server bridge there is only one HTTP session - that's the whole point. There is still a separate IClientSession and IServerSession, because they provide different features and are kind of hard-wired into the application. The only difference is that the context switch does not happen via HTTP call (service tunnel). See the implementation in BridgeToServerBeanDecorator#ensureRunInServerContext.
To get a list of active client sessions, you could create your own little registry (just an @ApplicationScoped bean with a list). Each client session can then be registered in the execLoad() method and unregistered again in the execStore() method.
The admin interface on /process is a little bit old fashioned and not very flexible. I wouldn't rely too much on it.
Kind regards,
Beat
|
|
|
Re: Server/Ui-Session List and the Upcoming Release [message #1863724 is a reply to message #1863709] |
Fri, 23 February 2024 11:19 |
|
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 113 times)
[Updated on: Fri, 23 February 2024 20:57] Report message to a moderator
|
|
|
Re: Server/Ui-Session List and the Upcoming Release [message #1863740 is a reply to message #1863724] |
Fri, 23 February 2024 19:31 |
Nils Israel Messages: 72 Registered: May 2010 |
Member |
|
|
Hi Beat and Claudio,
Thanks, I will look into writing the little session registry.
As for Open Telemetry, yes, I discovered it a few days ago and integrated it directly into our existing Grafana stack. :) The biggest Scout application we are developing is a frontend for a Spring Boot application. We use Promtail/Loki for log collection and aggregation for both Spring Boot and Scout, Tempo for observability in Spring Boot (along with the Scout correlation id that we pass in the REST calls), and Prometheus for metrics for Spring Boot and now the Scout application.
But right now there are only very basic jvm metrics that Scout provides, right? Is there any plan to integrate the metrics from the mentioned MBeans?
Best regards
Nils
[Updated on: Fri, 23 February 2024 19:33] Report message to a moderator
|
|
| | | |
Re: Server/Ui-Session List and the Upcoming Release [message #1864485 is a reply to message #1864002] |
Tue, 19 March 2024 13:36 |
Nils Israel Messages: 72 Registered: May 2010 |
Member |
|
|
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 May 09 00:56:26 GMT 2024
Powered by FUDForum. Page generated in 0.04496 seconds
|