Examples done.

This commit is contained in:
danidemi 2016-11-06 15:57:07 +01:00
parent 189bee7872
commit 9bd83d921c
25 changed files with 197 additions and 272 deletions

View File

@ -7,27 +7,17 @@
<name>logmdcndc</name> <name>logmdcndc</name>
<description>tutorial on logging with MDC and NDC</description> <description>tutorial on logging with MDC and NDC</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-context</artifactId>
<version>4.3.3.RELEASE</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-webmvc</artifactId>
<scope>test</scope> <version>4.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency> </dependency>
<!--log4j dependencies --> <!--log4j dependencies -->

View File

@ -2,6 +2,8 @@ package com.baeldung.mdc;
public interface BusinessService { public interface BusinessService {
boolean transfer(Long amount); /** Sample service transferring a given amount of money.
* @return {@code true} when the transfer complete successfully, {@code false} otherwise. */
boolean transfer(long amount);
} }

View File

@ -1,15 +1,19 @@
package com.baeldung.mdc; package com.baeldung.mdc;
/**
* A fake {@link BusinessService} simulating an actual one.
*/
public class DefaultBusinessService implements BusinessService { public class DefaultBusinessService implements BusinessService {
@Override public boolean transfer(long amount) {
public boolean transfer(Long amount) {
try { try {
Thread.sleep((long) (Math.random()*1000)); // let's pause randomly to properly simulate an actual system.
Thread.sleep((long) (500 + Math.random()*500));
} catch (InterruptedException e) { } catch (InterruptedException e) {
// should not happen // should never happen
} }
return Math.random() >= 0.5; // let's simulate both failing and successful transfers
return Math.random() >= 0.25;
} }
} }

View File

@ -9,21 +9,20 @@ public abstract class DelegateBusiness {
this.delegate = delegate; this.delegate = delegate;
} }
public DelegateBusiness() { public DelegateBusiness() {
this( new DefaultBusinessService() ); this( new DefaultBusinessService() );
} }
public boolean transfer(Long amount) { public boolean transfer(long amount) {
preTransfer(); preTransfer(amount);
boolean outcome = delegate.transfer(amount); boolean outcome = delegate.transfer(amount);
postTransfer(outcome); postTransfer(amount, outcome);
return outcome; return outcome;
} }
abstract protected void postTransfer(boolean outcome); abstract protected void postTransfer(long amount, boolean outcome);
abstract protected void preTransfer(); abstract protected void preTransfer(long amount);

View File

@ -1,46 +1,25 @@
package com.baeldung.mdc; package com.baeldung.mdc;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import org.apache.log4j.MDC; import org.apache.log4j.Logger;
import com.baeldung.mdc.log4j.Log4jBusinessService; import com.baeldung.mdc.log4j.Log4JRunnable;
public class GenericApp { public class GenericApp {
public static void main(String[] args) { public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3); ExecutorService executor = Executors.newFixedThreadPool(3);
TransactionFactory transactionFactory = new TransactionFactory(); TransactionFactory transactionFactory = new TransactionFactory();
for(int i=0; i<10; i++){ for(int i=0; i<10; i++){
final Transaction tx = transactionFactory.newInstance();
TransactionContext tx = transactionFactory.buildTransaction(); executor.submit(new Log4JRunnable(tx));
executor.submit(new Runnable() {
@Override
public void run() {
new DelegateBusiness() {
@Override
protected void preTransfer() {
MDC.put("transaction.id", tx.getTransactionId());
MDC.put("transaction.owner", tx.getOwner());
MDC.put("transaction.createdAt", tx.getCreatedAt());
} }
@Override executor.shutdown();
protected void postTransfer(boolean outcome) {
// TODO Auto-generated method stub
}
}.transfer(
tx.getAmount()
);
}
});
}
} }
} }

View File

@ -2,18 +2,18 @@ package com.baeldung.mdc;
import java.util.Date; import java.util.Date;
public class TransactionContext { public class Transaction {
private String transactionId; private String transactionId;
private String owner; private String owner;
private Date createdAt; private Date createdAt;
private Long amount; private Long amount;
public TransactionContext(String transactionId, String owner) { public Transaction(String transactionId, String owner, long amount) {
this.transactionId = transactionId; this.transactionId = transactionId;
this.owner = owner; this.owner = owner;
this.createdAt = new Date(); this.createdAt = new Date();
this.amount = (long) (Math.random()*100); this.amount = amount;
} }
public String getOwner() { public String getOwner() {

View File

@ -1,10 +1,20 @@
package com.baeldung.mdc; package com.baeldung.mdc;
import static java.lang.Math.floor;
import static java.lang.Math.random;
import java.util.UUID;
public class TransactionFactory { public class TransactionFactory {
public TransactionContext buildTransaction() { private static final String[] NAMES = {"John", "Susan", "Marc", "Samantha"};
TransactionContext ctx = new TransactionContext("" + Math.random(), "owner" + Math.random());
return ctx; public Transaction newInstance() {
String transactionId = UUID.randomUUID().toString();
String owner = NAMES[ (int) floor(random()*NAMES.length) ];
long amount = (long) (random()*1500 + 500);
Transaction tx = new Transaction(transactionId, owner, amount);
return tx;
} }
} }

View File

@ -0,0 +1,22 @@
package com.baeldung.mdc.log4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.baeldung.mdc.DelegateBusiness;
final class Log4JBusinessService extends DelegateBusiness {
private static final Logger logger = LogManager.getLogger();
@Override
protected void preTransfer(long amount) {
logger.info("Preparing to transfer {}$.");
}
@Override
protected void postTransfer(long amount, boolean outcome) {
logger.info("Has transfer of {}$ completed successfully ? {}.");
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.mdc.log4j;
import org.apache.log4j.MDC;
import com.baeldung.mdc.Transaction;
public class Log4JRunnable implements Runnable {
private final Transaction tx;
public Log4JRunnable(Transaction tx) {
this.tx = tx;
}
public void run() {
MDC.put("transaction.id", tx.getTransactionId());
MDC.put("transaction.owner", tx.getOwner());
MDC.put("transaction.createdAt", tx.getCreatedAt());
new Log4JBusinessService().transfer(tx.getAmount());
MDC.clear();
}
}

View File

@ -1,17 +0,0 @@
package com.baeldung.mdc.log4j;
import org.apache.log4j.Logger;
import com.baeldung.mdc.BusinessService;
public class Log4jBusinessService implements BusinessService {
private final static Logger logger = Logger.getLogger(Log4jBusinessService.class);
@Override
public boolean transfer(Long amount) {
logger.info("Executing transaction #" + amount );
return false;
}
}

View File

@ -1,17 +0,0 @@
package com.baeldung.mdc.log4j;
public class Log4jDemo {
public static void main(String[] args) throws InterruptedException {
Log4jExecutor greeter = new Log4jExecutor();
Thread thread1 = new Thread(greeter);
Thread thread2 = new Thread(greeter);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}

View File

@ -1,21 +0,0 @@
package com.baeldung.mdc.log4j;
import org.apache.log4j.MDC;
import com.baeldung.mdc.TransactionContext;
import com.baeldung.mdc.TransactionFactory;
public class Log4jExecutor implements Runnable {
public void run() {
TransactionContext ctx = new TransactionFactory().buildTransaction();
MDC.put("transaction.id", ctx.getTransactionId());
MDC.put("transaction.owner", ctx.getOwner());
MDC.put("transaction.createdAt", ctx.getCreatedAt());
new Log4jBusinessService().transfer(ctx.getAmount());
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.mdc.log4j2;
import org.apache.log4j.Logger;
import com.baeldung.mdc.DelegateBusiness;
final class Log4J2BusinessService extends DelegateBusiness {
private Logger logger = Logger.getLogger(Log4J2BusinessService.class);
@Override
protected void preTransfer(long amount) {
logger .info("Preparing to transfer " + amount + "$.");
}
@Override
protected void postTransfer(long amount, boolean outcome) {
logger.info("Has transfer of " + amount + "$ completed successfully ? " + outcome + ".");
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.mdc.log4j2;
import org.apache.logging.log4j.ThreadContext;
import com.baeldung.mdc.Transaction;
final class Log4J2Runnable implements Runnable {
private final Transaction tx;
Log4J2Runnable(Transaction tx) {
this.tx = tx;
}
public void run() {
ThreadContext.put("transaction.id", tx.getTransactionId());
ThreadContext.put("transaction.owner", tx.getOwner());
ThreadContext.put("transaction.createdAt", tx.getCreatedAt().toString());
new Log4J2BusinessService().transfer(tx.getAmount());
ThreadContext.clearAll();
}
}

View File

@ -1,20 +0,0 @@
package com.baeldung.mdc.log4j2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.baeldung.mdc.BusinessService;
public class Log4j2BusinessService implements BusinessService {
private static final Logger logger = LogManager.getLogger(); //Log4j2BusinessService.class);
@Override
public boolean transfer(Long amount) {
logger.info("Executing transaction #{}", amount );
return false;
}
}

View File

@ -1,17 +0,0 @@
package com.baeldung.mdc.log4j2;
public class Log4j2Demo {
public static void main(String[] args) throws InterruptedException {
Log4j2Executor greeter = new Log4j2Executor();
Thread thread1 = new Thread(greeter);
Thread thread2 = new Thread(greeter);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}

View File

@ -1,21 +0,0 @@
package com.baeldung.mdc.log4j2;
import org.apache.logging.log4j.ThreadContext;
import com.baeldung.mdc.TransactionContext;
import com.baeldung.mdc.TransactionFactory;
public class Log4j2Executor implements Runnable {
public void run() {
TransactionContext ctx = new TransactionFactory().buildTransaction();
ThreadContext.put("transaction.id", ctx.getTransactionId());
ThreadContext.put("transaction.owner", ctx.getOwner());
ThreadContext.put("transaction.createdAt", ctx.getCreatedAt().toString());
new Log4j2BusinessService().transfer(ctx.getAmount());
}
}

View File

@ -1,18 +0,0 @@
package com.baeldung.mdc.logback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baeldung.mdc.BusinessService;
public class LogbackBusinessService implements BusinessService {
private static final Logger logger = LoggerFactory.getLogger(LogbackBusinessService.class);
@Override
public boolean transfer(Long amount) {
logger.info("Executing transaction #{}", amount);
return false;
}
}

View File

@ -1,17 +0,0 @@
package com.baeldung.mdc.logback;
public class LogbackDemo {
public static void main(String[] args) throws InterruptedException {
LogbackExecutor greeter = new LogbackExecutor();
Thread thread1 = new Thread(greeter);
Thread thread2 = new Thread(greeter);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
}
}

View File

@ -1,23 +0,0 @@
package com.baeldung.mdc.logback;
import org.slf4j.MDC;
import com.baeldung.mdc.TransactionContext;
import com.baeldung.mdc.TransactionFactory;
public class LogbackExecutor implements Runnable {
public void run() {
TransactionContext ctx = new TransactionFactory().buildTransaction();
MDC.put("transaction.id", ctx.getTransactionId());
MDC.put("transaction.owner", ctx.getOwner());
MDC.put("transaction.createdAt", ctx.getCreatedAt().toString());
new LogbackBusinessService().transfer(ctx.getAmount());
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.mdc.slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baeldung.mdc.DelegateBusiness;
final class Slf4jBusinessService extends DelegateBusiness {
private static final Logger logger = LoggerFactory.getLogger(Slf4jBusinessService.class);
@Override
protected void preTransfer(long amount) {
logger.info("Preparing to transfer " + amount + "$.");
}
@Override
protected void postTransfer(long amount, boolean outcome) {
logger.info("Has transfer of " + amount + "$ completed successfully ? " + outcome + ".");
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.mdc.slf4j;
import org.slf4j.MDC;
import com.baeldung.mdc.Transaction;
final class Slf4jRunnable implements Runnable {
private final Transaction tx;
Slf4jRunnable(Transaction tx) {
this.tx = tx;
}
public void run() {
MDC.put("transaction.id", tx.getTransactionId());
MDC.put("transaction.owner", tx.getOwner());
MDC.put("transaction.createdAt", tx.getCreatedAt().toString());
new Slf4jBusinessService().transfer(tx.getAmount());
MDC.clear();
}
}

View File

@ -1,12 +0,0 @@
package com.baeldung.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -1,18 +0,0 @@
package com.baeldung.web;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
@GetMapping("/echo")
public String echo(@RequestBody String body) {
return body;
}
}

View File

@ -2,11 +2,13 @@ log4j.appender.consoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout log4j.appender.consoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=/tmp/$X{transaction.owner} log4j.appender.file.File=/tmp/baeldung.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout=org.apache.log4j.PatternLayout
#note the %X{userName} - this is how you fetch data from Mapped Diagnostic Context (MDC) #note the %X{userName} - this is how you fetch data from Mapped Diagnostic Context (MDC)
log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %5p %c %x - %m - owner=%X{transaction.owner} creation=%X{transaction.createdAt}%n #log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %5p %c %x - %m - owner=%X{transaction.owner} creation=%X{transaction.createdAt}%n
log4j.appender.file.layout.ConversionPattern=%-4r [%t] %5p %c %x - %m - owner=%X{transaction.owner} creation=%X{transaction.createdAt}%n #log4j.appender.file.layout.ConversionPattern=%-4r [%t] %5p %c %x - %m - owner=%X{transaction.owner} creation=%X{transaction.createdAt}%n
log4j.appender.consoleAppender.layout.ConversionPattern=%-4r [%t] %5p %c %x - %m%n
log4j.appender.file.layout.ConversionPattern=%-4r [%t] %5p %c %x - %m%n
log4j.rootLogger = ALL, consoleAppender, file log4j.rootLogger = TRACE, consoleAppender, file