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