Repository: james-project Updated Branches: refs/heads/master 4bf777b1e -> 4bdc00096
JAMES-2340 Add metrics for SpamAssassin Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/4bdc0009 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/4bdc0009 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/4bdc0009 Branch: refs/heads/master Commit: 4bdc000960fe867a40b21c6f5881658863d6ee0b Parents: b296483 Author: benwa <btell...@linagora.com> Authored: Mon Mar 26 11:31:35 2018 +0700 Committer: Matthieu Baechler <matth...@apache.org> Committed: Mon Mar 26 15:30:11 2018 +0200 ---------------------------------------------------------------------- .../mailbox/spamassassin/SpamAssassin.java | 9 ++- server/container/util/pom.xml | 4 + .../james/util/scanner/SpamAssassinInvoker.java | 82 ++++++++++---------- .../util/scanner/SpamAssassinInvokerTest.java | 3 +- .../james/transport/mailets/SpamAssassin.java | 7 +- .../transport/mailets/SpamAssassinTest.java | 3 +- .../fastfail/SpamAssassinHandler.java | 11 ++- .../smtpserver/SpamAssassinHandlerTest.java | 7 +- 8 files changed, 76 insertions(+), 50 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java ---------------------------------------------------------------------- diff --git a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java b/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java index fb27e9a..a2c19f0 100644 --- a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java +++ b/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java @@ -23,6 +23,7 @@ import java.util.List; import javax.inject.Inject; +import org.apache.james.metrics.api.MetricFactory; import org.apache.james.util.Host; import org.apache.james.util.scanner.SpamAssassinInvoker; @@ -30,17 +31,19 @@ import com.github.fge.lambdas.Throwing; public class SpamAssassin { + private final MetricFactory metricFactory; private final SpamAssassinConfiguration spamAssassinConfiguration; @Inject - public SpamAssassin(SpamAssassinConfiguration spamAssassinConfiguration) { + public SpamAssassin(MetricFactory metricFactory, SpamAssassinConfiguration spamAssassinConfiguration) { + this.metricFactory = metricFactory; this.spamAssassinConfiguration = spamAssassinConfiguration; } public void learnSpam(List<InputStream> messages, String user) { if (spamAssassinConfiguration.isEnable()) { Host host = spamAssassinConfiguration.getHost().get(); - SpamAssassinInvoker invoker = new SpamAssassinInvoker(host.getHostName(), host.getPort()); + SpamAssassinInvoker invoker = new SpamAssassinInvoker(metricFactory, host.getHostName(), host.getPort()); messages .forEach(Throwing.consumer(message -> invoker.learnAsSpam(message, user))); } @@ -49,7 +52,7 @@ public class SpamAssassin { public void learnHam(List<InputStream> messages, String user) { if (spamAssassinConfiguration.isEnable()) { Host host = spamAssassinConfiguration.getHost().get(); - SpamAssassinInvoker invoker = new SpamAssassinInvoker(host.getHostName(), host.getPort()); + SpamAssassinInvoker invoker = new SpamAssassinInvoker(metricFactory, host.getHostName(), host.getPort()); messages .forEach(Throwing.consumer(message -> invoker.learnAsHam(message, user))); } http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/server/container/util/pom.xml ---------------------------------------------------------------------- diff --git a/server/container/util/pom.xml b/server/container/util/pom.xml index c602027..653949f 100644 --- a/server/container/util/pom.xml +++ b/server/container/util/pom.xml @@ -40,6 +40,10 @@ <scope>test</scope> </dependency> <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>metrics-api</artifactId> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/server/container/util/src/main/java/org/apache/james/util/scanner/SpamAssassinInvoker.java ---------------------------------------------------------------------- diff --git a/server/container/util/src/main/java/org/apache/james/util/scanner/SpamAssassinInvoker.java b/server/container/util/src/main/java/org/apache/james/util/scanner/SpamAssassinInvoker.java index 80d1534..fdc3560 100644 --- a/server/container/util/src/main/java/org/apache/james/util/scanner/SpamAssassinInvoker.java +++ b/server/container/util/src/main/java/org/apache/james/util/scanner/SpamAssassinInvoker.java @@ -34,9 +34,11 @@ import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.apache.commons.io.IOUtils; +import org.apache.james.metrics.api.MetricFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.github.fge.lambdas.Throwing; import com.google.common.base.Splitter; import com.google.common.collect.Lists; @@ -47,24 +49,35 @@ import com.google.common.collect.Lists; public class SpamAssassinInvoker { private static final Logger LOGGER = LoggerFactory.getLogger(SpamAssassinInvoker.class); + enum MessageClass { + HAM("ham"), + SPAM("spam"); + + private final String value; + + MessageClass(String value) { + this.value = value; + } + } + private static final int SPAM_INDEX = 1; private static final int HITS_INDEX = 3; private static final int REQUIRED_HITS_INDEX = 5; private static final String CRLF = "\r\n"; + private final MetricFactory metricFactory; private final String spamdHost; - private final int spamdPort; /** * Init the spamassassin invoker - * + * * @param spamdHost * The host on which spamd runs * @param spamdPort - * The port on which spamd listen */ - public SpamAssassinInvoker(String spamdHost, int spamdPort) { + public SpamAssassinInvoker(MetricFactory metricFactory, String spamdHost, int spamdPort) { + this.metricFactory = metricFactory; this.spamdHost = spamdHost; this.spamdPort = spamdPort; } @@ -84,7 +97,11 @@ public class SpamAssassinInvoker { } public SpamAssassinResult scanMail(MimeMessage message) throws MessagingException { - return scanMailWithAdditionalHeaders(message); + return metricFactory.withMetric( + "spamAssassin-check", + Throwing.supplier( + () -> scanMailWithoutAdditionalHeaders(message)) + .sneakyThrow()); } public SpamAssassinResult scanMailWithAdditionalHeaders(MimeMessage message, String... additionalHeaders) throws MessagingException { @@ -122,6 +139,10 @@ public class SpamAssassinInvoker { } } + public SpamAssassinResult scanMailWithoutAdditionalHeaders(MimeMessage message) throws MessagingException { + return scanMailWithAdditionalHeaders(message); + } + private SpamAssassinResult processSpam(String line) { List<String> elements = Lists.newArrayList(Splitter.on(' ').split(line)); @@ -161,36 +182,11 @@ public class SpamAssassinInvoker { * if an error occured during learning. */ public boolean learnAsSpam(InputStream message, String user) throws MessagingException { - try (Socket socket = new Socket(spamdHost, spamdPort); - OutputStream out = socket.getOutputStream(); - PrintWriter writer = new PrintWriter(out); - BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { - - byte[] byteArray = IOUtils.toByteArray(message); - writer.write("TELL SPAMC/1.2"); - writer.write(CRLF); - writer.write("Content-length: " + byteArray.length); - writer.write(CRLF); - writer.write("Message-class: spam"); - writer.write(CRLF); - writer.write("Set: local, remote"); - writer.write(CRLF); - writer.write("User: " + user); - writer.write(CRLF); - writer.write(CRLF); - writer.flush(); - - out.write(byteArray); - out.flush(); - socket.shutdownOutput(); - - return in.lines() - .anyMatch(this::hasBeenSet); - } catch (UnknownHostException e) { - throw new MessagingException("Error communicating with spamd. Unknown host: " + spamdHost); - } catch (IOException e) { - throw new MessagingException("Error communicating with spamd on " + spamdHost + ":" + spamdPort, e); - } + return metricFactory.withMetric( + "spamAssassin-spam-report", + Throwing.supplier( + () -> reportMessageAs(message, user, MessageClass.SPAM)) + .sneakyThrow()); } /** @@ -202,17 +198,25 @@ public class SpamAssassinInvoker { * if an error occured during learning. */ public boolean learnAsHam(InputStream message, String user) throws MessagingException { + return metricFactory.withMetric( + "spamAssassin-ham-report", + Throwing.supplier( + () -> reportMessageAs(message, user, MessageClass.HAM)) + .sneakyThrow()); + } + + private boolean reportMessageAs(InputStream message, String user, MessageClass messageClass) throws MessagingException { try (Socket socket = new Socket(spamdHost, spamdPort); - OutputStream out = socket.getOutputStream(); - PrintWriter writer = new PrintWriter(out); - BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { + OutputStream out = socket.getOutputStream(); + PrintWriter writer = new PrintWriter(out); + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) { byte[] byteArray = IOUtils.toByteArray(message); writer.write("TELL SPAMC/1.2"); writer.write(CRLF); writer.write("Content-length: " + byteArray.length); writer.write(CRLF); - writer.write("Message-class: ham"); + writer.write("Message-class: " + messageClass.value); writer.write(CRLF); writer.write("Set: local, remote"); writer.write(CRLF); http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/server/container/util/src/test/java/org/apache/james/util/scanner/SpamAssassinInvokerTest.java ---------------------------------------------------------------------- diff --git a/server/container/util/src/test/java/org/apache/james/util/scanner/SpamAssassinInvokerTest.java b/server/container/util/src/test/java/org/apache/james/util/scanner/SpamAssassinInvokerTest.java index 0f995a0..4901ba4 100644 --- a/server/container/util/src/test/java/org/apache/james/util/scanner/SpamAssassinInvokerTest.java +++ b/server/container/util/src/test/java/org/apache/james/util/scanner/SpamAssassinInvokerTest.java @@ -25,6 +25,7 @@ import java.nio.charset.StandardCharsets; import javax.mail.internet.MimeMessage; +import org.apache.james.metrics.api.NoopMetricFactory; import org.apache.james.util.MimeMessageUtil; import org.apache.james.util.scanner.SpamAssassinExtension.SpamAssassin; import org.junit.jupiter.api.BeforeEach; @@ -41,7 +42,7 @@ public class SpamAssassinInvokerTest { @BeforeEach public void setup(SpamAssassin spamAssassin) throws Exception { this.spamAssassin = spamAssassin; - testee = new SpamAssassinInvoker(spamAssassin.getIp(), spamAssassin.getBindingPort()); + testee = new SpamAssassinInvoker(new NoopMetricFactory(), spamAssassin.getIp(), spamAssassin.getBindingPort()); } @Test http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java index bb8189c..6112cb3 100644 --- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java +++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java @@ -26,6 +26,7 @@ import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.apache.james.core.MailAddress; +import org.apache.james.metrics.api.MetricFactory; import org.apache.james.user.api.UsersRepository; import org.apache.james.user.api.UsersRepositoryException; import org.apache.james.util.Port; @@ -69,13 +70,15 @@ public class SpamAssassin extends GenericMailet { public static final String DEFAULT_HOST = "127.0.0.1"; public static final int DEFAULT_PORT = 783; + private final MetricFactory metricFactory; private final UsersRepository usersRepository; private String spamdHost; private int spamdPort; @Inject - public SpamAssassin(UsersRepository usersRepository) { + public SpamAssassin(MetricFactory metricFactory, UsersRepository usersRepository) { + this.metricFactory = metricFactory; this.usersRepository = usersRepository; } @@ -94,7 +97,7 @@ public class SpamAssassin extends GenericMailet { MimeMessage message = mail.getMessage(); // Invoke SpamAssassin connection and scan the message - SpamAssassinInvoker sa = new SpamAssassinInvoker(spamdHost, spamdPort); + SpamAssassinInvoker sa = new SpamAssassinInvoker(metricFactory, spamdHost, spamdPort); mail.getRecipients() .forEach( Throwing.consumer((MailAddress recipient) -> querySpamAssassin(mail, message, sa, recipient)) http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java ---------------------------------------------------------------------- diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java index a4a1049..466ad0c 100644 --- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java +++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java @@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import javax.mail.MessagingException; import org.apache.james.core.builder.MimeMessageBuilder; +import org.apache.james.metrics.api.NoopMetricFactory; import org.apache.james.user.memory.MemoryUsersRepository; import org.apache.james.util.Port; import org.apache.james.util.scanner.SpamAssassinResult; @@ -41,7 +42,7 @@ public class SpamAssassinTest { @Rule public MockSpamdTestRule spamd = new MockSpamdTestRule(); - private SpamAssassin mailet = new SpamAssassin(MemoryUsersRepository.withVirtualHosting()); + private SpamAssassin mailet = new SpamAssassin(new NoopMetricFactory(), MemoryUsersRepository.withVirtualHosting()); @Test public void initShouldSetDefaultSpamdHostWhenNone() throws Exception { http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java ---------------------------------------------------------------------- diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java index 14e6095..efa9611 100644 --- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java +++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java @@ -19,11 +19,13 @@ package org.apache.james.smtpserver.fastfail; +import javax.inject.Inject; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; +import org.apache.james.metrics.api.MetricFactory; import org.apache.james.protocols.api.ProtocolSession.State; import org.apache.james.protocols.api.handler.ProtocolHandler; import org.apache.james.protocols.smtp.SMTPSession; @@ -69,6 +71,8 @@ import org.slf4j.LoggerFactory; public class SpamAssassinHandler implements JamesMessageHook, ProtocolHandler { private static final Logger LOGGER = LoggerFactory.getLogger(SpamAssassinHandler.class); + private final MetricFactory metricFactory; + /** The port spamd is listen on */ private int spamdPort = 783; @@ -78,6 +82,11 @@ public class SpamAssassinHandler implements JamesMessageHook, ProtocolHandler { /** The hits on which the message get rejected */ private double spamdRejectionHits = 0.0; + @Inject + public SpamAssassinHandler(MetricFactory metricFactory) { + this.metricFactory = metricFactory; + } + /** * Set the host the spamd daemon is running at * @@ -114,7 +123,7 @@ public class SpamAssassinHandler implements JamesMessageHook, ProtocolHandler { try { MimeMessage message = mail.getMessage(); - SpamAssassinInvoker sa = new SpamAssassinInvoker(spamdHost, spamdPort); + SpamAssassinInvoker sa = new SpamAssassinInvoker(metricFactory, spamdHost, spamdPort); SpamAssassinResult result = sa.scanMail(message); // Add the headers http://git-wip-us.apache.org/repos/asf/james-project/blob/4bdc0009/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java ---------------------------------------------------------------------- diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java index eeb79af..5507679 100644 --- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java +++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java @@ -27,6 +27,7 @@ import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; import org.apache.james.core.builder.MimeMessageBuilder; +import org.apache.james.metrics.api.NoopMetricFactory; import org.apache.james.protocols.smtp.SMTPSession; import org.apache.james.protocols.smtp.hook.HookResult; import org.apache.james.protocols.smtp.hook.HookReturnCode; @@ -111,7 +112,7 @@ public class SpamAssassinHandlerTest { public void testNonSpam() throws Exception { SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage("test"))); - SpamAssassinHandler handler = new SpamAssassinHandler(); + SpamAssassinHandler handler = new SpamAssassinHandler(new NoopMetricFactory()); handler.setSpamdHost(SPAMD_HOST); handler.setSpamdPort(spamd.getPort()); @@ -128,7 +129,7 @@ public class SpamAssassinHandlerTest { public void testSpam() throws Exception { SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE))); - SpamAssassinHandler handler = new SpamAssassinHandler(); + SpamAssassinHandler handler = new SpamAssassinHandler(new NoopMetricFactory()); handler.setSpamdHost(SPAMD_HOST); handler.setSpamdPort(spamd.getPort()); @@ -144,7 +145,7 @@ public class SpamAssassinHandlerTest { public void testSpamReject() throws Exception { SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE))); - SpamAssassinHandler handler = new SpamAssassinHandler(); + SpamAssassinHandler handler = new SpamAssassinHandler(new NoopMetricFactory()); handler.setSpamdHost(SPAMD_HOST); handler.setSpamdPort(spamd.getPort()); --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org