2013-06-21 96 views
3

我使用Grizzly爲澤西島應用程序提供服務,同時使用Logback來滿足我的日誌記錄需求。請不存在這裏沒有涉及Servlet S,我火了一切「手動」使用了一塊這樣的代碼:如何使用Grizzly/Jersey登錄客戶端地址進行日誌記錄?

final URI uri = /* this is a configuration option */   
this.server = new HttpServer(); 
final NetworkListener nl = new NetworkListener(
    "grizzly", uri.getHost(), uri.getPort()); 
server.addListener(nl); 

final GuiceComponentProviderFactory gcpf = 
    new GuiceComponentProviderFactory(rc, inj); 
final HttpHandler processor = ContainerFactory.createContainer(
    HttpHandler.class, rc, gcpf); 
this.server.getServerConfiguration().addHttpHandler(
    processor, uri.getPath()); 
server.start(); 

現在我想使用的logback的MDC功能,使的套接字地址客戶端在日誌記錄中可見。爲了這個目的,我需要一些地方來把一個監聽器連接到HTTP處理中,這個處理會得到有關傳入請求的通知(我可以把地址放入MDC中)以及請求完成時(這樣我可以清理MDC)。一種方法我跟着是掛鉤一Container*Filter實例與新澤西州,這是這樣的:

class MdcFilter implements 
     ContainerRequestFilter, ContainerResponseFilter { 

    @Override 
    public ContainerRequest filter(ContainerRequest request) { 
     MDC.put("http-client", "foo" /* no way to get the address here */); 
     return request; 
    } 

    @Override 
    public ContainerResponse filter(
      ContainerRequest request, 
      ContainerResponse response) { 

     MDC.remove("http-client"); 
     return response; 
    } 

} 

不幸的是,澤西ContainerRequest不提供有關連接的客戶端信息(如凸輪一個真正的驚喜)。

我懷疑類似的界面應該與灰熊本身存在,但我無法挖掘出來。

回答

4

對於Grizzly,相關的API被稱爲HttpServerProbe。利用這一點,把它歸結爲這樣的事:

final HttpServer server = new org.glassfish.grizzly.http.server.HttpServer(); 
server.addListener(new NetworkListener("grizzly", "localhost", 8080)); 
server.getServerConfiguration().addHttpHandler(
    new StaticHttpHandler("/var/www/"), "/"); 

server.getServerConfiguration().getMonitoringConfig().getWebServerConfig() 
    .addProbes(new HttpServerProbe.Adapter() { 

    @Override 
    public void onRequestReceiveEvent(
     HttpServerFilter filter, 
     Connection connection, 
     Request request) { 

     System.out.println(request.getRemoteAddr()); 
     MDC.put("http-client", request.getRemoteAddr()); 
    } 

    @Override 
    public void onRequestCompleteEvent(
     HttpServerFilter filter, 
     Connection connection, 
     Response response) { 

     MDC.remove("http-client"); 
    } 
} 

server.start(); 

注意,有更多的可能是相關的,如暫停,恢復和取消的事件。這些應該也可以處理,特別是如果使用長輪詢(也稱爲Comet,又名什麼)。但基本上這是要掛鉤的地方。

+0

這似乎只有在服務器以特定方式啓動時纔有效。請您分享啓動服務器的代碼進行比較。 –

+0

我將上面的示例代碼擴展爲可運行的,並且只是檢查它實際上是否有效,@WolfgangFahl。讓我知道這是否有問題。 – Waldheinz

+0

謝謝 - 我現在也工作了。不幸的是,GrizzlyServerFactory代碼沒有選項*不*啓動服務器。在啓動服務器後添加監控時,它似乎不起作用。 –

-1

在你MdcFilter,嘗試將HttpServletRequest注入類,並使用它作爲你通常會調用getRemoteAddr()或任何其他這樣的功能,如:

class MdcFilter implements 
    ContainerRequestFilter, ContainerResponseFilter { 

    @Context 
    protected HttpServletRequest r; 

    @Override 
    public ContainerRequest filter(ContainerRequest request) { 
     MDC.put("http-client", "foo" r.getRemoteAddr()); 
     return request; 
    } 

    @Override 
    public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { 
     MDC.remove("http-client"); 
     return response; 
    } 
} 

我測試了這一點,使用類似的方法來「用手發射東西」,在那種情況下,它爲我解決了問題。我認爲它也適用於你。

+0

不幸的是,在我的情況下沒有'HttpServletRequest'。我甚至不得不引入一個新的依賴關係(我在2.5版中選擇了「servlet-api」)以使該接口可用。但即使如此,它並沒有被注入。當取消引用'r'時會導致'NullPointerException'。 – Waldheinz