Skip to content

Commit

Permalink
JAMES-2114 MDC contectual logging for JMAP
Browse files Browse the repository at this point in the history
  • Loading branch information
chibenwa committed Aug 24, 2017
1 parent 47ceea4 commit 176d7bf
Show file tree
Hide file tree
Showing 20 changed files with 249 additions and 25 deletions.
Expand Up @@ -58,6 +58,7 @@ private JMAPServer(JMAPConfiguration jmapConfiguration,
.with(authenticationServlet)
.filter(JMAPUrls.AUTHENTICATION)
.with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("POST").and("OPTIONS").only()))
.and(new MDCFilter())
.only()
.serve(JMAPUrls.JMAP)
.with(jmapServlet)
Expand All @@ -66,16 +67,19 @@ private JMAPServer(JMAPConfiguration jmapConfiguration,
.and(new LogbookFilter(logbook()))
.and(userProvisioningFilter)
.and(defaultMailboxesProvisioningFilter)
.and(new MDCFilter())
.only()
.serveAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
.with(downloadServlet)
.filterAsOneLevelTemplate(JMAPUrls.DOWNLOAD)
.with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
.and(new MDCFilter())
.only()
.serve(JMAPUrls.UPLOAD)
.with(uploadServlet)
.filterAsOneLevelTemplate(JMAPUrls.UPLOAD)
.with(new AllowAllCrossOriginRequests(bypass(authenticationFilter).on("OPTIONS").only()))
.and(new MDCFilter())
.only()
.build()));
} else {
Expand Down
Expand Up @@ -45,6 +45,7 @@
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Throwables;

public class JMAPServlet extends HttpServlet {

Expand All @@ -67,13 +68,13 @@ public JMAPServlet(RequestHandler requestHandler, MetricFactory metricFactory) {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
TimeMetric timeMetric = metricFactory.timer("JMAP-request");
try {
List<Object[]> responses =
List<Object[]> responses =
requestAsJsonStream(req)
.map(ProtocolRequest::deserialize)
.map(x -> AuthenticatedProtocolRequest.decorate(x, req))
.flatMap(requestHandler::handle)
.map(ProtocolResponse::asProtocolSpecification)
.collect(Collectors.toList());
.map(ProtocolRequest::deserialize)
.map(x -> AuthenticatedProtocolRequest.decorate(x, req))
.flatMap(this::handle)
.map(ProtocolResponse::asProtocolSpecification)
.collect(Collectors.toList());

resp.setContentType(JSON_CONTENT_TYPE);
objectMapper.writeValue(resp.getOutputStream(), responses);
Expand All @@ -87,7 +88,15 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S
timeMetric.stopAndPublish();
}
}


private Stream<? extends ProtocolResponse> handle(AuthenticatedProtocolRequest request) {
try {
return requestHandler.handle(request);
} catch (IOException e) {
throw Throwables.propagate(e);
}
}

private Stream<JsonNode[]> requestAsJsonStream(HttpServletRequest req) throws IOException, JsonParseException, JsonMappingException {
return Arrays.stream(
objectMapper.readValue(req.getInputStream(), JsonNode[][].class));
Expand Down
@@ -0,0 +1,56 @@
/****************************************************************
* 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.jmap;

import java.io.Closeable;
import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.james.util.MDCBuilder;

public class MDCFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {

}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try (Closeable closeable =
MDCBuilder.create()
.addContext(MDCBuilder.PROTOCOL, "JMAP")
.addContext(MDCBuilder.IP, request.getRemoteAddr())
.addContext(MDCBuilder.HOST, request.getRemoteHost())
.build()) {
chain.doFilter(request, response);
}
}

@Override
public void destroy() {

}
}
Expand Up @@ -19,6 +19,8 @@

package org.apache.james.jmap.methods;

import java.io.Closeable;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
Expand All @@ -41,6 +43,7 @@
import org.apache.james.mailbox.model.MailboxQuery;
import org.apache.james.metrics.api.MetricFactory;
import org.apache.james.metrics.api.TimeMetric;
import org.apache.james.util.MDCBuilder;
import org.apache.james.util.OptionalConverter;

import com.google.common.annotations.VisibleForTesting;
Expand Down Expand Up @@ -80,13 +83,21 @@ public Stream<JmapResponse> process(JmapRequest request, ClientId clientId, Mail
Preconditions.checkArgument(request instanceof GetMailboxesRequest);
GetMailboxesRequest mailboxesRequest = (GetMailboxesRequest) request;
TimeMetric timeMetric = metricFactory.timer(JMAP_PREFIX + METHOD_NAME.getName());
try {
try (Closeable closeable =
MDCBuilder.create()
.addContext(MDCBuilder.ACTION, "GET_MAILBOXES")
.addContext("accountId", mailboxesRequest.getAccountId())
.addContext("mailboxIds", mailboxesRequest.getIds())
.addContext("properties", mailboxesRequest.getProperties())
.build()) {
return Stream.of(
JmapResponse.builder().clientId(clientId)
.response(getMailboxesResponse(mailboxesRequest, mailboxSession))
.properties(mailboxesRequest.getProperties().map(this::ensureContainsId))
.responseName(RESPONSE_NAME)
.build());
} catch (IOException e) {
throw Throwables.propagate(e);
} finally {
timeMetric.stopAndPublish();
}
Expand Down
Expand Up @@ -19,6 +19,8 @@

package org.apache.james.jmap.methods;

import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.Set;
Expand All @@ -45,6 +47,7 @@
import org.apache.james.mailbox.model.SearchQuery;
import org.apache.james.metrics.api.MetricFactory;
import org.apache.james.metrics.api.TimeMetric;
import org.apache.james.util.MDCBuilder;

import com.github.steveash.guavate.Guavate;
import com.google.common.annotations.VisibleForTesting;
Expand Down Expand Up @@ -94,13 +97,28 @@ public Stream<JmapResponse> process(JmapRequest request, ClientId clientId, Mail

GetMessageListRequest messageListRequest = (GetMessageListRequest) request;
GetMessageListResponse messageListResponse = getMessageListResponse(messageListRequest, mailboxSession);
try {
try (Closeable closeable =
MDCBuilder.create()
.addContext(MDCBuilder.ACTION, "GET_MESSAGE_LIST")
.addContext("accountId", messageListRequest.getAccountId())
.addContext("limit", messageListRequest.getLimit())
.addContext("anchor", messageListRequest.getAnchor())
.addContext("offset", messageListRequest.getAnchorOffset())
.addContext("properties", messageListRequest.getFetchMessageProperties())
.addContext("position", messageListRequest.getPosition())
.addContext("filters", messageListRequest.getFilter())
.addContext("sorts", messageListRequest.getSort())
.addContext("isFetchMessage", messageListRequest.isFetchMessages())
.addContext("isCollapseThread", messageListRequest.isCollapseThreads())
.build()) {
Stream<JmapResponse> jmapResponse = Stream.of(JmapResponse.builder().clientId(clientId)
.response(messageListResponse)
.responseName(RESPONSE_NAME)
.build());
return Stream.concat(jmapResponse,
processGetMessages(messageListRequest, messageListResponse, clientId, mailboxSession));
} catch (IOException e) {
throw Throwables.propagate(e);
} finally {
timeMetric.stopAndPublish();
}
Expand Down
Expand Up @@ -19,6 +19,8 @@

package org.apache.james.jmap.methods;

import java.io.Closeable;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
Expand All @@ -45,6 +47,7 @@
import org.apache.james.mailbox.model.MessageResult;
import org.apache.james.metrics.api.MetricFactory;
import org.apache.james.metrics.api.TimeMetric;
import org.apache.james.util.MDCBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -95,13 +98,21 @@ public Stream<JmapResponse> process(JmapRequest request, ClientId clientId, Mail
GetMessagesRequest getMessagesRequest = (GetMessagesRequest) request;
MessageProperties outputProperties = getMessagesRequest.getProperties().toOutputProperties();
TimeMetric timeMetric = metricFactory.timer(JMAP_PREFIX + METHOD_NAME.getName());
try {
try (Closeable closeable =
MDCBuilder.create()
.addContext(MDCBuilder.ACTION, "GET_MESSAGES")
.addContext("accountId", getMessagesRequest.getAccountId())
.addContext("ids", getMessagesRequest.getIds())
.addContext("properties", getMessagesRequest.getProperties())
.build()) {
return Stream.of(JmapResponse.builder().clientId(clientId)
.response(getMessagesResponse(mailboxSession, getMessagesRequest))
.responseName(RESPONSE_NAME)
.properties(outputProperties.getOptionalMessageProperties())
.filterProvider(buildOptionalHeadersFilteringFilterProvider(outputProperties))
.build());
} catch (IOException e) {
throw Throwables.propagate(e);
} finally {
timeMetric.stopAndPublish();
}
Expand Down
Expand Up @@ -19,6 +19,8 @@

package org.apache.james.jmap.methods;

import java.io.Closeable;
import java.io.IOException;
import java.util.stream.Stream;

import javax.inject.Inject;
Expand All @@ -33,9 +35,11 @@
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.metrics.api.MetricFactory;
import org.apache.james.metrics.api.TimeMetric;
import org.apache.james.util.MDCBuilder;
import org.apache.james.util.date.ZonedDateTimeProvider;

import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;

public class GetVacationResponseMethod implements Method {

Expand Down Expand Up @@ -71,12 +75,17 @@ public Stream<JmapResponse> process(JmapRequest request, ClientId clientId, Mail
Preconditions.checkArgument(request instanceof GetVacationRequest);

TimeMetric timeMetric = metricFactory.timer(JMAP_PREFIX + METHOD_NAME.getName());
try {
try (Closeable closeable =
MDCBuilder.create()
.addContext(MDCBuilder.ACTION, "VACATION")
.build()) {
return Stream.of(JmapResponse.builder()
.clientId(clientId)
.responseName(RESPONSE_NAME)
.response(process(mailboxSession))
.build());
} catch (IOException e) {
throw Throwables.propagate(e);
} finally {
timeMetric.stopAndPublish();
}
Expand Down
Expand Up @@ -19,6 +19,7 @@

package org.apache.james.jmap.methods;

import java.io.Closeable;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
Expand All @@ -33,6 +34,7 @@
import org.apache.james.jmap.model.AuthenticatedProtocolRequest;
import org.apache.james.jmap.model.ProtocolResponse;
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.util.MDCBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -52,11 +54,19 @@ public RequestHandler(Set<Method> methods, JmapRequestParser jmapRequestParser,
.collect(Collectors.toMap(Method::requestHandled, Function.identity()));
}

public Stream<ProtocolResponse> handle(AuthenticatedProtocolRequest request) {
return Optional.ofNullable(methods.get(request.getMethodName()))
.map(extractAndProcess(request))
.map(jmapResponseWriter::formatMethodResponse)
.orElseThrow(() -> new IllegalStateException("unknown method " + request.getMethodName()));
public Stream<ProtocolResponse> handle(AuthenticatedProtocolRequest request) throws IOException {
Optional<MailboxSession> mailboxSession = Optional.ofNullable(request.getMailboxSession());
try (Closeable closeable =
MDCBuilder.create()
.addContext(MDCBuilder.USER, mailboxSession.map(MailboxSession::getUser).map(MailboxSession.User::getUserName))
.addContext(MDCBuilder.SESSION_ID, mailboxSession.map(MailboxSession::getSessionId))
.addContext(MDCBuilder.ACTION, request.getMethodName().getName())
.build()) {
return Optional.ofNullable(methods.get(request.getMethodName()))
.map(extractAndProcess(request))
.map(jmapResponseWriter::formatMethodResponse)
.orElseThrow(() -> new IllegalStateException("unknown method " + request.getMethodName()));
}
}

private Function<Method, Stream<JmapResponse>> extractAndProcess(AuthenticatedProtocolRequest request) {
Expand Down
Expand Up @@ -19,6 +19,8 @@

package org.apache.james.jmap.methods;

import java.io.Closeable;
import java.io.IOException;
import java.util.Set;
import java.util.stream.Stream;

Expand All @@ -30,9 +32,11 @@
import org.apache.james.mailbox.MailboxSession;
import org.apache.james.metrics.api.MetricFactory;
import org.apache.james.metrics.api.TimeMetric;
import org.apache.james.util.MDCBuilder;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;

public class SetMailboxesMethod implements Method {

Expand Down Expand Up @@ -66,13 +70,21 @@ public Stream<JmapResponse> process(JmapRequest request, ClientId clientId, Mail
Preconditions.checkArgument(request instanceof SetMailboxesRequest);

TimeMetric timeMetric = metricFactory.timer(JMAP_PREFIX + METHOD_NAME.getName());
try {
SetMailboxesRequest setMailboxesRequest = (SetMailboxesRequest) request;
SetMailboxesRequest setMailboxesRequest = (SetMailboxesRequest) request;
try (Closeable closeable =
MDCBuilder.create()
.addContext(MDCBuilder.ACTION, "SET_MAILBOXES")
.addContext("create", setMailboxesRequest.getCreate())
.addContext("update", setMailboxesRequest.getUpdate())
.addContext("destroy", setMailboxesRequest.getDestroy())
.build()) {
return Stream.of(
JmapResponse.builder().clientId(clientId)
.response(setMailboxesResponse(setMailboxesRequest, mailboxSession))
.responseName(RESPONSE_NAME)
.build());
} catch (IOException e) {
throw Throwables.propagate(e);
} finally {
timeMetric.stopAndPublish();
}
Expand Down

0 comments on commit 176d7bf

Please sign in to comment.