This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 802ec0146e7fc51377b732511dfc1d9f8913e736
Author: Benoit TELLIER <btell...@linagora.com>
AuthorDate: Thu Nov 21 10:53:53 2024 +0100

    JAMES-4091 Add connection Date to IMAP channel description
---
 .../main/java/org/apache/james/core/ConnectionDescription.java |  2 ++
 .../java/org/apache/james/imapserver/netty/IMAPServer.java     | 10 ++++++++++
 .../james/imapserver/netty/ImapChannelUpstreamHandler.java     |  5 +++++
 .../java/org/apache/james/imapserver/netty/NettyConstants.java |  2 ++
 .../memory/MemoryWebAdminServerIntegrationTest.java            |  3 ++-
 .../apache/james/protocols/webadmin/ProtocolServerRoutes.java  |  7 +++++++
 6 files changed, 28 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/james/core/ConnectionDescription.java 
b/core/src/main/java/org/apache/james/core/ConnectionDescription.java
index fc30273d82..bcfe61810f 100644
--- a/core/src/main/java/org/apache/james/core/ConnectionDescription.java
+++ b/core/src/main/java/org/apache/james/core/ConnectionDescription.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.core;
 
+import java.time.Instant;
 import java.util.Map;
 import java.util.Optional;
 
@@ -26,6 +27,7 @@ public record ConnectionDescription(
     String protocol,
     String endpoint,
     Optional<String> remoteAddress,
+    Optional<Instant> connectionDate,
     boolean isActive,
     boolean isOpen,
     boolean isWritable,
diff --git 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
index f1d8853e2d..d96dfe53bd 100644
--- 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
+++ 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
@@ -29,6 +29,7 @@ import java.util.LinkedHashMap;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
@@ -74,6 +75,7 @@ import io.netty.channel.ChannelPipeline;
 import io.netty.channel.group.DefaultChannelGroup;
 import io.netty.handler.codec.haproxy.HAProxyMessageDecoder;
 import io.netty.handler.stream.ChunkedWriteHandler;
+import io.netty.util.AttributeKey;
 import io.netty.util.concurrent.GlobalEventExecutor;
 
 
@@ -83,6 +85,7 @@ import io.netty.util.concurrent.GlobalEventExecutor;
 public class IMAPServer extends AbstractConfigurableAsyncServer implements 
ImapConstants, IMAPServerMBean, NettyConstants,
     Disconnector, ConnectionDescriptionSupplier {
     private static final Logger LOG = 
LoggerFactory.getLogger(IMAPServer.class);
+    public static final AttributeKey<Instant> CONNECTION_DATE = 
AttributeKey.newInstance("connectionDate");
 
     public static class AuthenticationConfiguration {
         private static final boolean PLAIN_AUTH_DISALLOWED_DEFAULT = true;
@@ -288,6 +291,8 @@ public class IMAPServer extends 
AbstractConfigurableAsyncServer implements ImapC
 
             @Override
             public void initChannel(Channel channel) {
+                channel.attr(CONNECTION_DATE).set(Clock.systemUTC().instant());
+
                 ChannelPipeline pipeline = channel.pipeline();
                 channel.config().setWriteBufferWaterMark(writeBufferWaterMark);
                 pipeline.addLast(TIMEOUT_HANDLER, new 
ImapIdleStateHandler(timeout));
@@ -377,6 +382,7 @@ public class IMAPServer extends 
AbstractConfigurableAsyncServer implements ImapC
                     "IMAP",
                     jmxName,
                     
Optional.ofNullable(channel.remoteAddress()).map(this::addressAsString),
+                    
Optional.ofNullable(channel.attr(CONNECTION_DATE)).flatMap(attribute -> 
Optional.ofNullable(attribute.get())),
                     channel.isActive(),
                     channel.isOpen(),
                     channel.isWritable(),
@@ -391,6 +397,10 @@ public class IMAPServer extends 
AbstractConfigurableAsyncServer implements ImapC
                         "isIdling", 
Boolean.toString(imapSession.flatMap(session -> 
Optional.ofNullable(session.getSelected()))
                             .map(SelectedMailbox::isIdling)
                             .orElse(false)),
+                        "requestCount", 
Long.toString(Optional.ofNullable(channel.attr(REQUEST_COUNTER))
+                            .flatMap(attribute -> 
Optional.ofNullable(attribute.get()))
+                            .map(AtomicLong::get)
+                            .orElse(0L)),
                         "userAgent", imapSession.flatMap(s -> 
Optional.ofNullable(s.getAttribute("userAgent")))
                             .map(Object::toString)
                             .orElse("")));
diff --git 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
index 4274e1cdab..8d478926ed 100644
--- 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
+++ 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
@@ -32,6 +32,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
 
 import javax.net.ssl.SSLHandshakeException;
 
@@ -218,6 +219,7 @@ public class ImapChannelUpstreamHandler extends 
ChannelInboundHandlerAdapter imp
             authenticationConfiguration.isPlainAuthEnabled(), sessionId,
             authenticationConfiguration.getOidcSASLConfiguration());
         ctx.channel().attr(IMAP_SESSION_ATTRIBUTE_KEY).set(imapsession);
+        ctx.channel().attr(REQUEST_COUNTER).set(new AtomicLong());
         ctx.channel().attr(LINEARIZER_ATTRIBUTE_KEY).set(new 
ImapLinerarizer());
         MDCBuilder boundMDC = IMAPMDCContext.boundMDC(ctx)
             .addToContext(MDCBuilder.SESSION_ID, sessionId.asString());
@@ -401,6 +403,9 @@ public class ImapChannelUpstreamHandler extends 
ChannelInboundHandlerAdapter imp
         imapCommandsMetric.increment();
         ImapSession session = 
ctx.channel().attr(IMAP_SESSION_ATTRIBUTE_KEY).get();
         Attribute<Disposable> disposableAttribute = 
ctx.channel().attr(REQUEST_IN_FLIGHT_ATTRIBUTE_KEY);
+        Optional.ofNullable(ctx.channel().attr(REQUEST_COUNTER))
+            .flatMap(counter -> Optional.ofNullable(counter.get()))
+            .ifPresent(AtomicLong::incrementAndGet);
 
         ImapLinerarizer linearalizer = 
ctx.channel().attr(LINEARIZER_ATTRIBUTE_KEY).get();
         synchronized (linearalizer) {
diff --git 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyConstants.java
 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyConstants.java
index 2aa10f32f4..372fc0a262 100644
--- 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyConstants.java
+++ 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyConstants.java
@@ -19,6 +19,7 @@
 package org.apache.james.imapserver.netty;
 
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.james.imap.api.process.ImapSession;
 
@@ -41,6 +42,7 @@ public interface NettyConstants {
     String HEARTBEAT_HANDLER = "heartbeatHandler";
 
     AttributeKey<ImapSession> IMAP_SESSION_ATTRIBUTE_KEY = 
AttributeKey.valueOf("ImapSession");
+    AttributeKey<AtomicLong> REQUEST_COUNTER = 
AttributeKey.valueOf("RequestCounter");
     AttributeKey<Disposable> REQUEST_IN_FLIGHT_ATTRIBUTE_KEY = 
AttributeKey.valueOf("requestInFlight");
     AttributeKey<ImapChannelUpstreamHandler.ImapLinerarizer> 
LINEARIZER_ATTRIBUTE_KEY = AttributeKey.valueOf("linearizer");
     AttributeKey<Runnable> BACKPRESSURE_CALLBACK = 
AttributeKey.valueOf("BACKPRESSURE_CALLBACK");
diff --git 
a/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryWebAdminServerIntegrationTest.java
 
b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryWebAdminServerIntegrationTest.java
index caf94d403e..156637f646 100644
--- 
a/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryWebAdminServerIntegrationTest.java
+++ 
b/server/protocols/webadmin-integration-test/memory-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/memory/MemoryWebAdminServerIntegrationTest.java
@@ -76,6 +76,7 @@ class MemoryWebAdminServerIntegrationTest extends 
WebAdminServerIntegrationTest
             .body("[0].username", is("bob@domain"))
             .body("[0].isEncrypted", is(false))
             .body("[0].isEncrypted", is(false))
-            .body("[0].protocolSpecificInformation.userAgent", 
is("{name=Thunderbird, version=102.7.1}"));
+            .body("[0].protocolSpecificInformation.userAgent", 
is("{name=Thunderbird, version=102.7.1}"))
+            .body("[0].protocolSpecificInformation.requestCount", is("3"));
     }
 }
\ No newline at end of file
diff --git 
a/server/protocols/webadmin/webadmin-protocols/src/main/java/org/apache/james/protocols/webadmin/ProtocolServerRoutes.java
 
b/server/protocols/webadmin/webadmin-protocols/src/main/java/org/apache/james/protocols/webadmin/ProtocolServerRoutes.java
index d1ba81ee72..887626b42c 100644
--- 
a/server/protocols/webadmin/webadmin-protocols/src/main/java/org/apache/james/protocols/webadmin/ProtocolServerRoutes.java
+++ 
b/server/protocols/webadmin/webadmin-protocols/src/main/java/org/apache/james/protocols/webadmin/ProtocolServerRoutes.java
@@ -19,12 +19,15 @@
 
 package org.apache.james.protocols.webadmin;
 
+import java.time.Instant;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 
+import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import jakarta.inject.Inject;
 
 import org.apache.james.DisconnectorNotifier;
@@ -54,6 +57,7 @@ public class ProtocolServerRoutes implements Routes {
         String protocol,
         String endpoint,
         Optional<String> remoteAddress,
+        Optional<Instant> connectionDate,
         boolean isActive,
         boolean isOpen,
         boolean isWritable,
@@ -65,6 +69,7 @@ public class ProtocolServerRoutes implements Routes {
             return new ConnectionDescriptionDTO(domainObject.protocol(),
                 domainObject.endpoint(),
                 domainObject.remoteAddress(),
+                domainObject.connectionDate(),
                 domainObject.isActive(),
                 domainObject.isOpen(),
                 domainObject.isWritable(),
@@ -82,6 +87,8 @@ public class ProtocolServerRoutes implements Routes {
 
     static {
         OBJECT_MAPPER.registerModule(new Jdk8Module());
+        OBJECT_MAPPER.registerModule(new JavaTimeModule());
+        
OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
     }
 
     private final Set<CertificateReloadable.Factory> servers;


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org
For additional commands, e-mail: notifications-h...@james.apache.org

Reply via email to