You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2017/08/24 03:46:35 UTC
[10/38] james-project git commit: JAMES-2114 MDC logging context for
IMAP
http://git-wip-us.apache.org/repos/asf/james-project/blob/56974b95/server/protocols/protocols-imap4/pom.xml
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/pom.xml b/server/protocols/protocols-imap4/pom.xml
index c38e647..68ca0cf 100644
--- a/server/protocols/protocols-imap4/pom.xml
+++ b/server/protocols/protocols-imap4/pom.xml
@@ -43,6 +43,10 @@
</dependency>
<dependency>
<groupId>org.apache.james</groupId>
+ <artifactId>james-server-util-java8</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.james</groupId>
<artifactId>metrics-api</artifactId>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/james-project/blob/56974b95/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPMDCContext.java
----------------------------------------------------------------------
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPMDCContext.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPMDCContext.java
new file mode 100644
index 0000000..35ccf32
--- /dev/null
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPMDCContext.java
@@ -0,0 +1,78 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.imapserver.netty;
+
+import java.io.Closeable;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Optional;
+
+import org.apache.james.imap.api.process.SelectedMailbox;
+import org.apache.james.protocols.imap.IMAPSession;
+import org.apache.james.util.MDCBuilder;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelLocal;
+
+public class IMAPMDCContext {
+ public static Closeable from(ChannelHandlerContext ctx, ChannelLocal<Object> attributes) {
+ return MDCBuilder.create()
+ .addContext(from(attributes.get(ctx.getChannel())))
+ .addContext(MDCBuilder.PROTOCOL, "IMAP")
+ .addContext(MDCBuilder.IP, retrieveIp(ctx))
+ .addContext(MDCBuilder.HOST, retrieveHost(ctx))
+ .build();
+ }
+
+ private static String retrieveIp(ChannelHandlerContext ctx) {
+ SocketAddress remoteAddress = ctx.getChannel().getRemoteAddress();
+ if (remoteAddress instanceof InetSocketAddress) {
+ InetSocketAddress address = (InetSocketAddress) remoteAddress;
+ return address.getAddress().getHostAddress();
+ }
+ return remoteAddress.toString();
+ }
+
+ private static String retrieveHost(ChannelHandlerContext ctx) {
+ SocketAddress remoteAddress = ctx.getChannel().getRemoteAddress();
+ if (remoteAddress instanceof InetSocketAddress) {
+ InetSocketAddress address = (InetSocketAddress) remoteAddress;
+ return address.getHostName();
+ }
+ return remoteAddress.toString();
+ }
+
+ private static MDCBuilder from(Object o) {
+ return Optional.ofNullable(o)
+ .filter(object -> object instanceof IMAPSession)
+ .map(object -> (IMAPSession) object)
+ .map(imapSession -> MDCBuilder.create()
+ .addContext(MDCBuilder.SESSION_ID, imapSession.getSessionID())
+ .addContext(MDCBuilder.USER, imapSession.getUser())
+ .addContext(from(Optional.ofNullable(imapSession.getSelected()))))
+ .orElse(MDCBuilder.create());
+ }
+
+ private static MDCBuilder from(Optional<SelectedMailbox> selectedMailbox) {
+ return selectedMailbox
+ .map(value -> MDCBuilder.create()
+ .addContext("selectedMailbox", value.getPath().asString()))
+ .orElse(MDCBuilder.create());
+ }
+}
http://git-wip-us.apache.org/repos/asf/james-project/blob/56974b95/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapChannelUpstreamHandler.java
----------------------------------------------------------------------
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 48b522e..14d1a20 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
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.james.imapserver.netty;
+import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.function.Supplier;
@@ -34,8 +35,6 @@ import org.apache.james.imap.encode.ImapResponseComposer;
import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
import org.apache.james.imap.main.ResponseEncoder;
import org.apache.james.metrics.api.Metric;
-import org.apache.james.protocols.api.logger.ContextualLogger;
-import org.apache.james.protocols.imap.IMAPSession;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFutureListener;
@@ -95,28 +94,16 @@ public class ImapChannelUpstreamHandler extends SimpleChannelUpstreamHandler imp
}
private Logger getLogger(final ChannelHandlerContext ctx) {
- return new ContextualLogger(
- getUserSupplier(ctx),
- String.valueOf(ctx.getChannel().getId()),
- logger);
- }
-
- private Supplier<String> getUserSupplier(final ChannelHandlerContext ctx) {
- return () -> {
- Object o = attributes.get(ctx.getChannel());
- if (o instanceof IMAPSession) {
- IMAPSession session = (IMAPSession) o;
- return session.getUser();
- }
- return null;
- };
+ return logger;
}
@Override
public void channelBound(final ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
- ImapSession imapsession = new NettyImapSession(ctx.getChannel(), toLogSupplier(ctx), context, enabledCipherSuites, compress, plainAuthDisallowed);
- attributes.set(ctx.getChannel(), imapsession);
- super.channelBound(ctx, e);
+ try (Closeable closeable = IMAPMDCContext.from(ctx, attributes)) {
+ ImapSession imapsession = new NettyImapSession(ctx.getChannel(), () -> getLogger(ctx), context, enabledCipherSuites, compress, plainAuthDisallowed);
+ attributes.set(ctx.getChannel(), imapsession);
+ super.channelBound(ctx, e);
+ }
}
private Supplier<Logger> toLogSupplier(final ChannelHandlerContext ctx) {
@@ -125,119 +112,120 @@ public class ImapChannelUpstreamHandler extends SimpleChannelUpstreamHandler imp
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-
- InetSocketAddress address = (InetSocketAddress) ctx.getChannel().getRemoteAddress();
- getLogger(ctx).info("Connection closed for " + address.getAddress().getHostAddress());
-
- // remove the stored attribute for the channel to free up resources
- // See JAMES-1195
- ImapSession imapSession = (ImapSession) attributes.remove(ctx.getChannel());
- if (imapSession != null)
- imapSession.logout();
- imapConnectionsMetric.decrement();
-
- super.channelClosed(ctx, e);
- }
-
- @Override
- public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-
- InetSocketAddress address = (InetSocketAddress) ctx.getChannel().getRemoteAddress();
- getLogger(ctx).info("Connection established from " + address.getAddress().getHostAddress());
- imapConnectionsMetric.increment();
-
- ImapResponseComposer response = new ImapResponseComposerImpl(new ChannelImapResponseWriter(ctx.getChannel()));
- ctx.setAttachment(response);
+ try (Closeable closeable = IMAPMDCContext.from(ctx, attributes)) {
+ InetSocketAddress address = (InetSocketAddress) ctx.getChannel().getRemoteAddress();
+ getLogger(ctx).info("Connection closed for " + address.getAddress().getHostAddress());
- // write hello to client
- response.untagged().message("OK").message(hello).end();
- super.channelConnected(ctx, e);
+ // remove the stored attribute for the channel to free up resources
+ // See JAMES-1195
+ ImapSession imapSession = (ImapSession) attributes.remove(ctx.getChannel());
+ if (imapSession != null)
+ imapSession.logout();
+ imapConnectionsMetric.decrement();
+ super.channelClosed(ctx, e);
+ }
}
@Override
- public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
-
- getLogger(ctx).warn("Error while processing imap request", e.getCause());
-
- if (e.getCause() instanceof TooLongFrameException) {
-
- // Max line length exceeded
- // See RFC 2683 section 3.2.1
- //
- // "For its part, a server should allow for a command line of at
- // least
- // 8000 octets. This provides plenty of leeway for accepting
- // reasonable
- // length commands from clients. The server should send a BAD
- // response
- // to a command that does not end within the server's maximum
- // accepted
- // command length."
- //
- // See also JAMES-1190
- ImapResponseComposer composer = (ImapResponseComposer) ctx.getAttachment();
- composer.untaggedResponse(ImapConstants.BAD + " failed. Maximum command line length exceeded");
-
- } else {
-
- // logout on error not sure if that is the best way to handle it
- final ImapSession imapSession = (ImapSession) attributes.get(ctx.getChannel());
- if (imapSession != null)
- imapSession.logout();
+ public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+ try (Closeable closeable = IMAPMDCContext.from(ctx, attributes)) {
+ InetSocketAddress address = (InetSocketAddress) ctx.getChannel().getRemoteAddress();
+ getLogger(ctx).info("Connection established from " + address.getAddress().getHostAddress());
+ imapConnectionsMetric.increment();
- // Make sure we close the channel after all the buffers were flushed out
- Channel channel = ctx.getChannel();
- if (channel.isConnected()) {
- channel.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
- }
+ ImapResponseComposer response = new ImapResponseComposerImpl(new ChannelImapResponseWriter(ctx.getChannel()));
+ ctx.setAttachment(response);
+ // write hello to client
+ response.untagged().message("OK").message(hello).end();
+ super.channelConnected(ctx, e);
}
-
}
@Override
- public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
-
- imapCommandsMetric.increment();
- ImapSession session = (ImapSession) attributes.get(ctx.getChannel());
- ImapResponseComposer response = (ImapResponseComposer) ctx.getAttachment();
- ImapMessage message = (ImapMessage) e.getMessage();
- ChannelPipeline cp = ctx.getPipeline();
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
+ try (Closeable closeable = IMAPMDCContext.from(ctx, attributes)) {
+ getLogger(ctx).warn("Error while processing imap request", e.getCause());
+
+ if (e.getCause() instanceof TooLongFrameException) {
+
+ // Max line length exceeded
+ // See RFC 2683 section 3.2.1
+ //
+ // "For its part, a server should allow for a command line of at
+ // least
+ // 8000 octets. This provides plenty of leeway for accepting
+ // reasonable
+ // length commands from clients. The server should send a BAD
+ // response
+ // to a command that does not end within the server's maximum
+ // accepted
+ // command length."
+ //
+ // See also JAMES-1190
+ ImapResponseComposer composer = (ImapResponseComposer) ctx.getAttachment();
+ composer.untaggedResponse(ImapConstants.BAD + " failed. Maximum command line length exceeded");
- try {
- if (cp.get(NettyConstants.EXECUTION_HANDLER) != null) {
- cp.addBefore(NettyConstants.EXECUTION_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
} else {
- cp.addBefore(NettyConstants.CORE_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
- }
- final ResponseEncoder responseEncoder = new ResponseEncoder(encoder, response, session);
- processor.process(message, responseEncoder, session);
+ // logout on error not sure if that is the best way to handle it
+ final ImapSession imapSession = (ImapSession) attributes.get(ctx.getChannel());
+ if (imapSession != null)
+ imapSession.logout();
- if (session.getState() == ImapSessionState.LOGOUT) {
// Make sure we close the channel after all the buffers were flushed out
Channel channel = ctx.getChannel();
if (channel.isConnected()) {
channel.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
- }
- final IOException failure = responseEncoder.getFailure();
- if (failure != null) {
- final Logger logger = session.getLog();
- logger.info(failure.getMessage());
- if (logger.isDebugEnabled()) {
- logger.debug("Failed to write " + message, failure);
- }
- throw failure;
}
- } finally {
- ctx.getPipeline().remove(NettyConstants.HEARTBEAT_HANDLER);
}
+ }
- super.messageReceived(ctx, e);
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ try (Closeable closeable = IMAPMDCContext.from(ctx, attributes)) {
+ imapCommandsMetric.increment();
+ ImapSession session = (ImapSession) attributes.get(ctx.getChannel());
+ ImapResponseComposer response = (ImapResponseComposer) ctx.getAttachment();
+ ImapMessage message = (ImapMessage) e.getMessage();
+ ChannelPipeline cp = ctx.getPipeline();
+
+ try {
+ if (cp.get(NettyConstants.EXECUTION_HANDLER) != null) {
+ cp.addBefore(NettyConstants.EXECUTION_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
+ } else {
+ cp.addBefore(NettyConstants.CORE_HANDLER, NettyConstants.HEARTBEAT_HANDLER, heartbeatHandler);
+
+ }
+ final ResponseEncoder responseEncoder = new ResponseEncoder(encoder, response, session);
+ processor.process(message, responseEncoder, session);
+
+ if (session.getState() == ImapSessionState.LOGOUT) {
+ // Make sure we close the channel after all the buffers were flushed out
+ Channel channel = ctx.getChannel();
+ if (channel.isConnected()) {
+ channel.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
+ }
+ }
+ final IOException failure = responseEncoder.getFailure();
+
+ if (failure != null) {
+ final Logger logger = session.getLog();
+ logger.info(failure.getMessage());
+ if (logger.isDebugEnabled()) {
+ logger.debug("Failed to write " + message, failure);
+ }
+ throw failure;
+ }
+ } finally {
+ ctx.getPipeline().remove(NettyConstants.HEARTBEAT_HANDLER);
+ }
+ super.messageReceived(ctx, e);
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org