From cd8183800df6e756221e641d007a4f2df993b0a7 Mon Sep 17 00:00:00 2001 From: Rishabh Joshi Date: Fri, 17 Feb 2017 18:15:25 +0530 Subject: [PATCH] Added Action and a Filter for MDC. By default logs a UUID for each request. --- README.md | 55 ++++++------------- build.sbt | 1 + src/main/java/zyx/cba/EnableMDC.java | 18 ++++++ .../cba/MappedDiagnosticContextAction.java | 26 +++++++++ .../cba/MappedDiagnosticContextFilter.java | 47 ++++++++++++++++ ...MDCPropagatingDispatcherConfigurator.scala | 4 +- 6 files changed, 112 insertions(+), 39 deletions(-) create mode 100644 src/main/java/zyx/cba/EnableMDC.java create mode 100644 src/main/java/zyx/cba/MappedDiagnosticContextAction.java create mode 100644 src/main/java/zyx/cba/MappedDiagnosticContextFilter.java rename src/main/scala/{ => zyx/cba}/MDCPropagatingDispatcherConfigurator.scala (96%) diff --git a/README.md b/README.md index ea0ba70..e536206 100644 --- a/README.md +++ b/README.md @@ -11,51 +11,19 @@ A Mapped Diagnostic Context (MDC) propagation Akka Dispatcher for the asynchrono #### How To Use -##### Configure Jitpack 1. Add the JitPack repository to your build file - build.sbt ```scala resolvers += "jitpack" at "https://jitpack.io" ``` 2. Add the dependency ```scala -libraryDependencies += "com.github.rishabh9" % "mdc-propagation-dispatcher" % "v0.0.1" +libraryDependencies += "com.github.rishabh9" % "mdc-propagation-dispatcher" % "v0.0.2" ``` -##### Create a filter +3. Either add 'MappedDiagnosticContextFilter' to Filters.java ```java -public class MappedDiagnosticContextFilter extends Filter { +import zyx.cba.MappedDiagnosticContextFilter; - private final Executor exec; - - /** - * @param mat This object is needed to handle streaming of requests - * and responses. - * @param exec This class is needed to execute code asynchronously. - * It is used below by the thenAsyncApply method. - */ - @Inject - public MappedDiagnosticContextFilter(Materializer mat, Executor exec) { - super(mat); - this.exec = exec; - } - - @Override - public CompletionStage apply(Function> next, - Http.RequestHeader requestHeader) { - MDC.put("X-UUID", java.util.UUID.randomUUID()); - return next.apply(requestHeader).thenApplyAsync( - result -> { - MDC.remove("X-UUID"); - return result; - }, - exec - ); - } -} -``` - -##### Add to Filters.java -```java @Singleton public class Filters implements HttpFilters { private final MappedDiagnosticContextFilter mdcFilter; @@ -75,18 +43,29 @@ public class Filters implements HttpFilters { } ``` -##### Update your logging configuration +Or annotate your controllers/methods with 'EnableMDC' annotation +```java +import zyx.cba.EnableMDC; +import play.mvc.Controller; + +@EnableMDC +public class MyController extends Controller { + // ... +} +``` + +4. Update your logging configuration ```xml %d{HH:mm:ss.SSS} %coloredLevel %logger{35} %mdc{X-UUID:--} - %msg%n%rootException ``` -##### Update your application.conf +5. Update your application.conf ```hocon play { akka { actor { default-dispatcher { - type = "MDCPropagatingDispatcherConfigurator" + type = "zyx.cba.MDCPropagatingDispatcherConfigurator" } } } diff --git a/build.sbt b/build.sbt index 7f46220..2b0a14a 100644 --- a/build.sbt +++ b/build.sbt @@ -14,6 +14,7 @@ retrieveManaged := true libraryDependencies ++= Seq( "com.typesafe" % "config" % "1.3.0" % "provided", + "com.typesafe.play" %% "play" % "2.5.10" % "provided", "org.slf4j" % "slf4j-api" % "1.7.21" % "provided", "com.typesafe.akka" %% "akka-actor" % "2.4.12" % "provided" ) diff --git a/src/main/java/zyx/cba/EnableMDC.java b/src/main/java/zyx/cba/EnableMDC.java new file mode 100644 index 0000000..3b4ac54 --- /dev/null +++ b/src/main/java/zyx/cba/EnableMDC.java @@ -0,0 +1,18 @@ +package zyx.cba; + +import play.mvc.With; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author rishabh + */ +@With(MappedDiagnosticContextAction.class) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface EnableMDC { + boolean value() default true; +} diff --git a/src/main/java/zyx/cba/MappedDiagnosticContextAction.java b/src/main/java/zyx/cba/MappedDiagnosticContextAction.java new file mode 100644 index 0000000..fdbffbd --- /dev/null +++ b/src/main/java/zyx/cba/MappedDiagnosticContextAction.java @@ -0,0 +1,26 @@ +package zyx.cba; + + +import org.slf4j.MDC; +import play.mvc.Action; +import play.mvc.Http; +import play.mvc.Result; + +import java.util.UUID; +import java.util.concurrent.CompletionStage; + +/** + * @author rishabh + */ +public class MappedDiagnosticContextAction extends Action { + public CompletionStage call(Http.Context ctx) { + if (configuration.value()) { + MDC.put("X-UUID", UUID.randomUUID().toString()); + } + return delegate.call(ctx).whenComplete((result, throwable) -> { + if (configuration.value()) { + MDC.remove("X-UUID"); + } + }); + } +} diff --git a/src/main/java/zyx/cba/MappedDiagnosticContextFilter.java b/src/main/java/zyx/cba/MappedDiagnosticContextFilter.java new file mode 100644 index 0000000..5414bb9 --- /dev/null +++ b/src/main/java/zyx/cba/MappedDiagnosticContextFilter.java @@ -0,0 +1,47 @@ +package zyx.cba; + +import akka.stream.Materializer; +import org.slf4j.MDC; +import play.mvc.Filter; +import play.mvc.Http; +import play.mvc.Result; + +import javax.inject.Inject; +import java.util.UUID; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executor; +import java.util.function.Function; + +/** + * @author rishabh + */ +public class MappedDiagnosticContextFilter extends Filter { + + private final Executor exec; + + /** + * @param mat This object is needed to handle streaming of requests + * and responses. + * @param exec This class is needed to execute code asynchronously. + * It is used below by the thenAsyncApply method. + */ + @Inject + public MappedDiagnosticContextFilter(Materializer mat, Executor exec) { + super(mat); + this.exec = exec; + } + + @Override + public CompletionStage apply(Function> next, + Http.RequestHeader requestHeader) { + + MDC.put("X-UUID", UUID.randomUUID().toString()); + return next.apply(requestHeader).thenApplyAsync( + result -> { + MDC.remove("X-UUID"); + return result; + }, + exec + ); + } +} diff --git a/src/main/scala/MDCPropagatingDispatcherConfigurator.scala b/src/main/scala/zyx/cba/MDCPropagatingDispatcherConfigurator.scala similarity index 96% rename from src/main/scala/MDCPropagatingDispatcherConfigurator.scala rename to src/main/scala/zyx/cba/MDCPropagatingDispatcherConfigurator.scala index 6752436..d0aebb4 100644 --- a/src/main/scala/MDCPropagatingDispatcherConfigurator.scala +++ b/src/main/scala/zyx/cba/MDCPropagatingDispatcherConfigurator.scala @@ -1,3 +1,5 @@ +package zyx.cba + import java.util.concurrent.TimeUnit import akka.dispatch._ @@ -16,7 +18,7 @@ import scala.concurrent.duration.{Duration, FiniteDuration} * akka { * actor { * default-dispatcher = { - * type = "monitoring.MDCPropagatingDispatcherConfigurator" + * type = "zyx.cba.MDCPropagatingDispatcherConfigurator" * } * } * }