2016-06-01 1 views
8

저희 팀은 지정된 파일 로깅을 사용하는 NetBeans 용 플러그인을 개발 중입니다. 로깅 시스템은 SLF4J + Log4J2를 사용합니다. 내가 알고 있는데 유일한 구성 정보는 플러그인에 대한 로깅 특성을 가진 log4j2.xml 파일이며, 다음log4j2로 자바 로깅을 사용하여 플러그인으로 만든 로그 파일의 수명주기를 올바르게 관리하는 방법

LoggerContext loggerContext = (LoggerContext)LogManager.getContext(false); 
    loggerContext.reconfigure(); 

(내가 SLF4J를 사용하고 있습니다 및 넷빈즈 여기 정말 관련이없는 사실.)

내가 가진 질문은, 플러그인 시작시 로깅을 시작하고 플러그인 종료시 로깅을 중지하는 올바른 방법은 무엇입니까?

내가 최대 LoggerContext 보았다 (JVM은. 로그 파일이 자동으로 종료되지 않도록 넷빈즈와 함께가는 계속) 나는 stop()terminate() 방법을 볼 수 있지만 나는 응용 프로그램 LoggerContext를 사용하는 가정하는 방법에 대한 문서를 찾을 수 없습니다 , 그래서이 LifeCycle 물건이 내부 세부 사항이나 응용 프로그램이 사용하기로되어있는 게 뭔지 모르겠다.


좀 더 구체적인 세부 사항 :

우리의 플러그인 라이프 사이클은 아래 그림과 같이 보입니다은 (하나의 인스턴스 만이 시간에 실행되도록 허용된다). "A"와 "B"는 우리가 원하는 로그 구성을 의미합니다.

 [Something starts within the JVM to load log4j classes first. 
     It might be our plugin, it might be something else. 
A  log4j's default mechanism kicks in to create log configuration A] 
| 
| [time passes] 
| 
| [our plugin starts] 
A [log4j classes first loaded, 
| default mechanism kicks in to create log configuration A] 
A setup log configuration B 
A B log event 1 
A B log event 2 
A B log event 3 
A shutdown log configuration B 
| [our plugin exits] 
| 
| [time passes] 
| 
| [our plugin starts] 
A setup log configuration B 
A B log event 1 
A B log event 2 
A B log event 3 
A shutdown log configuration B 
| [our plugin exits] 
| 
| [time passes] 
| 
    [JVM exits] 

구성 A는 JVM과 연관되어 있으며 log4j가 처음 JVM에서로드 할 때 생성되는 기본 구성입니다.

구성 B는 플러그인에 의해 프로그래밍 방식으로 관리되며 구성 A와 관계없이 명시 적으로 시작/종료해야하며 구성 A는 영향을받지 않아야합니다.

log4j 2.0에서이를 수행 할 수있는 방법이 있습니까?

+1

두 개의 로그 구성을 동시에 활성화 하시겠습니까? 이것이 로그 이벤트 1, 2 및 3 중 A 및 B가 활성화 된 다이어그램입니다 ... –

+0

예. 플러그인이 글로벌 로깅 구성을 방해하지 않도록 (예 : '모든 ERROR 이벤트를 글로벌 로그에 기록') 플러그인이 플러그인 이벤트에 대해 자체 컨텍스트를 설정해야합니다. –

답변

2

Log4j 2.5에서는 Configurator.shutdown()을 호출 할 수 있습니다. Log4j 2.6에서는 LogManager.shutdown()을 호출 할 수 있습니다.

+0

하지만 플러그인을 사용하는 로깅 리소스 만 종료하는 방법은 무엇입니까? NetBeans에 로깅 및/또는 다른 플러그인에서 log4j를 사용하는 경우 플러그인에 대해 설정 한 모든 로깅 활동을 종료하지 않으려 고합니다. –

+1

플러그인/서블릿/등 여러 협력 응용 프로그램이 포함 된 JVM에서 log4j를 사용하는 방법을 알려주는 "큰 그림"설명서를 찾고 있습니다. –

2

응용 프로그램의 다른 구성 요소에 대해 LoggerContext을 안전하게 사용할 수 있습니다.

terminate()stop()은 완전히 동일합니다. 사실, 전자는 후자를 호출하고 더 이상 아무것도하지 않습니다. terminate()LoggerContext 자신의 api의 일부이며, stop()은 더 넓은 LifeCycle 인터페이스의 일부입니다.

로깅 컨텍스트를 올바르게 구현하려면 컨텍스트 선택기의 메커니즘을 사용하십시오. Lo4j2는 LogManager.getContext()에 의해 반환 될 컨텍스트를 선택하는 클래스에 대해 인터페이스 ContextSelector을 제공합니다. 몇 가지 구현이 즉시 제공됩니다.

  • BasicContextSelector은 현재 스레드를 기반으로 컨텍스트를 선택합니다.
  • BundleContextSelector OSGI 환경에서 사용하기위한 것입니다.
  • JndiContextSelector 단일 서블릿 컨테이너의 여러 웹 응용 프로그램 용.
  • ClassLoaderContextSelector은 호출자의 클래스 로더를 기반으로 컨텍스트를 선택합니다.

어떤 셀렉터를 사용할지 지정하려면 Log4jContextSelector Java 옵션을 설정하십시오. (이 코드는 플러그인의 스레드에서 실행해야합니다)를 플러그인이 방법을

-DLog4jContextSelector=org.apache.logging.log4j.core.selector.BasicContextSelector 

사용할 별도의 LoggerContext의 : 당신의 플러그인은 별도의 스레드에서 실행하는 경우

는 예를 들어, 당신은 BasicContextSelector를 선택할 수 있습니다 :

// Create a separate context for the plugin 
LoggerContext pluginContext = new LoggerContext("PluginContext"); 

// Setup pluginContext... 

// BasicContextSelector uses ContextAnchor.THREAD_CONTEXT 
// to bind contexts to threads: 
ContextAnchor.THREAD_CONTEXT.set(pluginContext); 

// Your plugin works and has access to your logging context 
LogManager.getContext(false); // Returns pluginContext 

// Stop and remove the plugin's logging context 
pluginContext.stop(); 
ContextAnchor.THREAD_CONTEXT.set(null); 

하여 플러그인의 구조에 따라, 당신은 꽤 쉽게, 이러한 구현 중 하나를 사용하거나 자신을 제공 할 수 있습니다, 당신은 다음과 같은 방법을 구현해야합니다 :

  • getContext()LogManager.getContext(...)에 제공된 매개 변수를 기반으로 새 컨텍스트를 만들거나 기존 컨텍스트를 반환하십시오.
  • getLoggerContexts() 사용 가능한 컨텍스트 (이전에 생성 한 컨텍스트)의 컬렉션을 반환합니다.
  • removeContext() 메모리가 중지 (종료) 될 때 메모리에서 컨텍스트를 제거합니다.
+0

이것은 로깅 이벤트가이 새로운 사용자 정의 컨텍스트로 이동하지만 아니요 더 이상 기본 컨텍스트로 이동합니까? 그들을 둘 다 가질 수있는 방법이 있습니까? –

+0

이벤트는 이벤트를 보내는 로거를 가져 오는 데 사용 된 컨텍스트로 이동합니다. 모든 로거는 특정 컨텍스트 (아키텍처 참조 : http://logging.apache.org/log4j/2.x/manual/architecture.html)에 의해 소유되므로 이벤트는 컨텍스트 중 하나만으로 이동합니다. 2 개의 문맥에 이벤트를 송신 할 필요가있는 경우는, 2 개의 로거 (getContext (true)로 취득 된 것)와 getContext (false)로 취득한 것, 2 개의 로거를 랩하는 자체의 Logger를 작성합니다. 그 두 로거에 위임 할 모든 로깅 작업. –

+1

좀 더 복잡하지만 더 관용적 인 해결책은 두 개의 표준 컨텍스트 (플러그인의 주 및 주)를 래핑하고 'getLogger()에서 두 개의 Logger'를 둘러싼 위의 래퍼를 반환하는 자체 LoggerContext를 구현하는 것입니다.)'. 그런 다음 사용자 지정 컨텍스트 선택기에서이 사용자 지정 컨텍스트를 반환 할 수 있습니다. 결과적으로 클라이언트 코드는 모든 래퍼에 대해 알지 않고 평상시처럼 로거를 사용하지만 모든 이벤트는 결국 플러그인과 기본 로거 모두에 전달됩니다. –