2013-10-25 9 views
1

Java EE OSGi 환경에서 로거를 올바르게 설정하는 방법에 대해서는 상당히 혼란 스럽습니다. WebSphere의 OSGi 엔터프라이즈 애플리케이션에서 로거를 설정하는 방법은 무엇입니까?

  • 이 클래스 로더의 마법을 수행하지 마십시오 (때문에 여러되고 있기에로)

    • 만 EBA 당 1 개 로그 파일 (번들 그룹) 응용 프로그램 서버 당
    • 여러 로그 파일 (고운 : 여기 내 요구 사항은 내가 사용하는 라이브러리가이 작업을 수행하는 경우에만 쓰고 싶지 않습니다.)
    • 하루가 끝날 때 로그 파일을 순환시켜야하며 동시에 7 개의 로그 파일 만 유지해야합니다.
    • EBA 당 로깅 번들 각 애플리케이션에 대해 자체 로깅 interop을 작성하도록 말하면 다른 개발자가 구매할 수 없습니다.
    • 우선 나는, 그러나 아무것도 나의 log4j.properties를 찾을 수 않는 우리의 다른 Java EE 애플리케이션 등의 log4j의 상단에 SLF4J를 사용하려고하여 WebSphere Application Server의 8.5.5

    작업을해야합니다. 나는 SLF4j를 가져 오는 변형을 시도해 보았고, 1 묶음으로 로딩 할 때 다른 로딩에서 로딩하지 못하게하는 문제도있었습니다.

    다음으로 PAX logger를 살펴 보았지만 EBA가 아닌 전역으로 기록되는 것으로 보입니다.

    OSGi LogService를 사용하면 내 번들이 WebSphere로 배포되지 않으므로 어쨌든 어떻게해야 내 요구 사항을 충족시킬 수 있는지 알 수 없습니다.

    내가 볼 수있는 유일한 옵션은 번들 -> 로그 파일 (클라이언트 클래스에서 FrameworkUtil.getBundle 사용)에 대한 레지스트리를 유지하는 자체 번들을 작성하고 그 안에 전체 로깅 프레임 워크를 구현하는 것입니다. 그것. 클래스 로더 격리 문제가있는 경우 실제 로깅을 수행하기 위해 EJB로 푸시 할 수 있습니다. 나는 이 정말로이 유일한 해결책이 아니길 바라고있다.

    누군가 나를 도울 일부 문서를 가리킬 수 있습니까 ??

    감사합니다.

  • 답변

    1

    사람들은 일반적으로 로그 서비스에 대해 혼란 스럽습니다 ... 로그 서비스는 로그를 저장하지 않으며, 단지 디스패처 역할을합니다. 로그 서비스는 초기 시작을위한 작은 버퍼가 있어야하고 버퍼를 확보하기위한 API를 제공하므로 혼란을 이해합니다.

    원하는 경우 로그 판독기 서비스와 함께 로그 수신기를 추가해야합니다. Declarative Services를 사용하면 원하는 것을 쉽게 얻을 수 있습니다. 이것은 귀하의 요구 사항을 구현하는 구성 요소입니다 :

    @Component(provide = {}, immediate = true) public class Logger extends Thread 
        implements LogListener { 
        final BlockingQueue<LogEntry> queue = new ArrayBlockingQueue<LogEntry>(1000); 
        File root; 
    
        @Reference void setLR(LogReaderService lr) { 
        lr.addLogListener(this); 
        } 
    
        @Activate void activate(BundleContext context, Map<String,Object> props) { 
        if (props.containsKey("root")) 
         root = new File((String) props.get("root")); 
        else 
         root = context.getDataFile("logs"); 
        root.mkdirs(); 
        start(); 
        } 
    
        @Deactivate void deactivate() { 
        interrupt(); 
        } 
    
        @Override public void logged(LogEntry entry) { 
        queue.offer(entry); // ignore full silently 
        } 
    
        public void run() { 
        while (true) 
         try { 
         LogEntry entry = queue.take(); 
         File file = getPath(entry); 
    
         if (file.isFile()) { 
          long days = TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() 
           - file.lastModified()); 
          if (days > 2) file.delete(); 
         } 
    
         try (OutputStream raf = new FileOutputStream(file, true)) { 
          String s = String.format("%tT [%03d] %s%n", entry.getTime(), entry 
           .getBundle().getBundleId(), entry.getMessage()); 
          raf.write(s.getBytes("UTF-8")); 
         } 
    
         } catch (InterruptedException ie) { 
         return; 
         } catch (Exception e) { 
         throw new RuntimeException(e); 
         } 
        } 
    
        private File getPath(LogEntry entry) { 
        long rollover = TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis()) % 7; 
        String eba = "eba"; // fill in eba from entry.getBundle()? 
        return new File(root, "log-" + eba + "-" + rollover + ".msg"); 
        } 
    } 
    

    물론 이것은 좀 더 효율적으로 수행 할 수 있지만 연습으로 남겨 둘 수 있습니다.

    +0

    그래서 내 솔루션을 작성하고 번들 당 로그 파일 용 레지스트리를 유지하는 것이 가장 좋습니다. 나는 더 나은 해결책이 없다는 것에 조금 실망하지만, 구현에 대해 나에게 머리를 쥐어 주었다. – Craig

    +0

    * 제공 주셔서 감사합니다 ... – Craig