2013-10-06 58 views
0
public class SessionLogger { 

    private final String sessionId; 

    public SessionLogger(String sessionId) { 
     this.sessionId = sessionId; 
    } 

    public void info(Log log, String message, Object... args) { 
     log.info(formatMessage(message, args)); 
    } 

    public void error(Log log, String message, Throwable t, Object... args) { 
     log.error(formatMessage(message, args), t); 
    } 

    private String formatMessage(String message, Object... args) { 
     for (int i = 0; i < args.length; i++) { 
      message = message.replaceFirst("\\{\\}", args[i].toString()); 
     } 
     return String.format("SessionId [%s]: %s", sessionId, message); 
    } 
} 

我想要做的是將Logger實例傳遞給SessionLogger類,我希望看到Logger初始化的類名。傳遞記錄器作爲另一個類的參數

public class A { 
    private static final Log log = LogFactory.getLog(A.class) 
    public void doIt() { 
    sessionLogger.info(log, "hello world"); 
    } 
} 

我希望看到A級日誌消息,而不是SessionLogger:

2013-10-07 00:29:27,328 INFO [main] (SessionLogger.java:17) - SessionId [123]: Hello world 

我已經公地logging.jar和log4j的類路徑,1.2.16.jar。記錄儀是剛剛發佈,這是預期的行爲org.apache.commons.logging.Log

更新

一個實例,引起Logger記錄的代碼,其中被調用日誌方法的線。所以它應該做某種方式的另一種方式

+0

>>原因記錄器記錄該代碼,其中日誌方法被調用<<的線。 。 。 這取決於你的log4j.properties的配置 - 你也可以輸出的記錄器的名稱,而不是(這應該是「A」) – cljk

+0

沒錯。但是,登錄代碼行也不錯。由於log4j的調用Thread.currentThread()。的getStackTrace()......讓在運行時的行號,我不能在這種情況下使用這種方法 – user12384512

回答

1

我認爲解決的辦法是寫這篇文章中提出了一個自定義的Log4j圖案佈局:http://fw-geekycoder.blogspot.com/2010/07/creating-log4j-custom-patternlayout.html

那麼你就不需要SessionLogger,這將顯著簡化代碼。

佈局:

public class MyPatternLayout extends PatternLayout { 

    @Override 
    protected PatternParser createPatternParser(String pattern) { 
     return new MyPatternParser(pattern); 
    } 
} 

模式解析器:

public class MyPatternParser extends PatternParser { 

    private static final char USERNAME_CHAR = 'S'; 

    public MyPatternParser(String pattern) { 
     super(pattern); 
    } 

    @Override 
    protected void finalizeConverter(char c) { 
     switch (c) { 
      case USERNAME_CHAR: 
       currentLiteral.setLength(0); 
       addConverter(new MyPatternConverter()); 
       break; 
      default: 
       super.finalizeConverter(c); 
     } 
    } 
} 

模式轉換器:

public class MyPatternConverter extends PatternConverter { 
    @Override 
    protected String convert(LoggingEvent event) { 
     // Retrieve SessionID 
     return "123"; 
    } 
} 

Log4j配置:

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> 

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> 
    <appender name="console" class="org.apache.log4j.ConsoleAppender"> 
     <param name="Target" value="System.out"/> 
     <layout class="MyPatternLayout"> 
      <param name="ConversionPattern" value="%d{HH:mm:ss,SSS} %-5p (%F:%L) - Session ID:%S %m%n"/> 
     </layout> 
    </appender> 

    <root> 
     <priority value ="debug" /> 
     <appender-ref ref="console" /> 
    </root> 

</log4j:configuration> 
1

在看過你想要實現的目標之後,我相信不用做那件棘手的SessionLogger的東西,使用MDC可能是一個更合理的選擇。

安裝在MDC會話ID(取決於您的應用程序的設計。對於Web應用程序,有一個Servlet過濾器做MDC設置工作是合理的),讓大家簡單地使用記錄儀正常。通過使用適當的模式,您可以將會話ID放入結果日誌消息中。

不知道MDC暴露在Apache的共享日誌記錄,但它在SLF4J Log4J的或可用。

只是好奇,沒有任何理由使用ACL(這是衆所周知的有相當多的問題)。考慮切換到近年來更廣泛採用的SLF4J。

+0

感謝分享MDC方法。但它不適合我,因爲它依賴於ThreadLocal變量。 – user12384512

+0

我很想知道爲什麼依賴ThreadLocal是一個問題?除非你正在做一些棘手的多線程的東西,ThreadLocal很少成爲一個問題。 ThreadLocal的使用量比預期的要多得多,例如在交易管理等。 –

+0

是的,有很多多線程,執行者,生產者/消費者等。它不是一個簡單的網絡應用 – user12384512

相關問題