org.eclipse.jetty.server.DebugListener Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
The newest version!
//
// ========================================================================
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Locale;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.server.handler.ContextHandler.ContextScopeListener;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* A Context Listener that produces additional debug.
* This listener if added to a ContextHandler, will produce additional debug information to
* either/or a specific log stream or the standard debug log.
* The events produced by {@link ServletContextListener}, {@link ServletRequestListener},
* {@link AsyncListener} and {@link ContextScopeListener} are logged.
*/
@ManagedObject("Debug Listener")
public class DebugListener extends AbstractLifeCycle implements ServletContextListener
{
private static final Logger LOG = Log.getLogger(DebugListener.class);
private static final DateCache __date = new DateCache("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
private final String _attr = String.format("__R%s@%x", this.getClass().getSimpleName(), System.identityHashCode(this));
private final PrintStream _out;
private boolean _renameThread;
private boolean _showHeaders;
private boolean _dumpContext;
public DebugListener()
{
this(null, false, false, false);
}
public DebugListener(@Name("renameThread") boolean renameThread, @Name("showHeaders") boolean showHeaders, @Name("dumpContext") boolean dumpContext)
{
this(null, renameThread, showHeaders, dumpContext);
}
public DebugListener(@Name("outputStream") OutputStream out, @Name("renameThread") boolean renameThread, @Name("showHeaders") boolean showHeaders, @Name("dumpContext") boolean dumpContext)
{
_out = out == null ? null : new PrintStream(out);
_renameThread = renameThread;
_showHeaders = showHeaders;
_dumpContext = dumpContext;
}
@ManagedAttribute("Rename thread within context scope")
public boolean isRenameThread()
{
return _renameThread;
}
public void setRenameThread(boolean renameThread)
{
_renameThread = renameThread;
}
@ManagedAttribute("Show request headers")
public boolean isShowHeaders()
{
return _showHeaders;
}
public void setShowHeaders(boolean showHeaders)
{
_showHeaders = showHeaders;
}
@ManagedAttribute("Dump contexts at start")
public boolean isDumpContext()
{
return _dumpContext;
}
public void setDumpContext(boolean dumpContext)
{
_dumpContext = dumpContext;
}
@Override
public void contextInitialized(ServletContextEvent sce)
{
sce.getServletContext().addListener(_servletRequestListener);
ContextHandler handler = ContextHandler.getContextHandler(sce.getServletContext());
handler.addEventListener(_contextScopeListener);
String cname = findContextName(sce.getServletContext());
log("^ ctx=%s %s", cname, sce.getServletContext());
if (_dumpContext)
{
if (_out == null)
{
handler.dumpStdErr();
System.err.println(Dumpable.KEY);
}
else
{
try
{
handler.dump(_out);
_out.println(Dumpable.KEY);
}
catch (Exception e)
{
LOG.warn(e);
}
}
}
}
@Override
public void contextDestroyed(ServletContextEvent sce)
{
String cname = findContextName(sce.getServletContext());
log("v ctx=%s %s", cname, sce.getServletContext());
}
protected String findContextName(ServletContext context)
{
if (context == null)
return null;
String n = (String)context.getAttribute(_attr);
if (n == null)
{
n = String.format("%s@%x", context.getContextPath(), context.hashCode());
context.setAttribute(_attr, n);
}
return n;
}
protected String findRequestName(ServletRequest request)
{
if (request == null)
return null;
HttpServletRequest r = (HttpServletRequest)request;
String n = (String)request.getAttribute(_attr);
if (n == null)
{
n = String.format("%s@%x", r.getRequestURI(), request.hashCode());
request.setAttribute(_attr, n);
}
return n;
}
protected void log(String format, Object... arg)
{
if (!isRunning())
return;
String s = String.format(format, arg);
long now = System.currentTimeMillis();
long ms = now % 1000;
if (_out != null)
_out.printf("%s.%03d:%s%n", __date.formatNow(now), ms, s);
if (LOG.isDebugEnabled())
LOG.info(s);
}
final AsyncListener _asyncListener = new AsyncListener()
{
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
String cname = findContextName(((AsyncContextEvent)event).getServletContext());
String rname = findRequestName(event.getAsyncContext().getRequest());
log("! ctx=%s r=%s onTimeout %s", cname, rname, ((AsyncContextEvent)event).getHttpChannelState());
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
String cname = findContextName(((AsyncContextEvent)event).getServletContext());
String rname = findRequestName(event.getAsyncContext().getRequest());
log("! ctx=%s r=%s onStartAsync %s", cname, rname, ((AsyncContextEvent)event).getHttpChannelState());
}
@Override
public void onError(AsyncEvent event) throws IOException
{
String cname = findContextName(((AsyncContextEvent)event).getServletContext());
String rname = findRequestName(event.getAsyncContext().getRequest());
log("!! ctx=%s r=%s onError %s %s", cname, rname, event.getThrowable(), ((AsyncContextEvent)event).getHttpChannelState());
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
AsyncContextEvent ace = (AsyncContextEvent)event;
String cname = findContextName(ace.getServletContext());
String rname = findRequestName(ace.getAsyncContext().getRequest());
Request br = Request.getBaseRequest(ace.getAsyncContext().getRequest());
Response response = br.getResponse();
String headers = _showHeaders ? ("\n" + response.getHttpFields().toString()) : "";
log("! ctx=%s r=%s onComplete %s %d%s", cname, rname, ace.getHttpChannelState(), response.getStatus(), headers);
}
};
final ServletRequestListener _servletRequestListener = new ServletRequestListener()
{
@Override
public void requestInitialized(ServletRequestEvent sre)
{
String cname = findContextName(sre.getServletContext());
HttpServletRequest r = (HttpServletRequest)sre.getServletRequest();
String rname = findRequestName(r);
DispatcherType d = r.getDispatcherType();
if (d == DispatcherType.REQUEST)
{
Request br = Request.getBaseRequest(r);
String headers = _showHeaders ? ("\n" + br.getMetaData().getFields().toString()) : "";
StringBuffer url = r.getRequestURL();
if (r.getQueryString() != null)
url.append('?').append(r.getQueryString());
log(">> %s ctx=%s r=%s %s %s %s %s %s%s", d,
cname,
rname,
d,
r.getMethod(),
url.toString(),
r.getProtocol(),
br.getHttpChannel(),
headers);
}
else
log(">> %s ctx=%s r=%s", d, cname, rname);
}
@Override
public void requestDestroyed(ServletRequestEvent sre)
{
String cname = findContextName(sre.getServletContext());
HttpServletRequest r = (HttpServletRequest)sre.getServletRequest();
String rname = findRequestName(r);
DispatcherType d = r.getDispatcherType();
if (sre.getServletRequest().isAsyncStarted())
{
sre.getServletRequest().getAsyncContext().addListener(_asyncListener);
log("<< %s ctx=%s r=%s async=true", d, cname, rname);
}
else
{
Request br = Request.getBaseRequest(r);
String headers = _showHeaders ? ("\n" + br.getResponse().getHttpFields().toString()) : "";
log("<< %s ctx=%s r=%s async=false %d%s", d, cname, rname, Request.getBaseRequest(r).getResponse().getStatus(), headers);
}
}
};
final ContextHandler.ContextScopeListener _contextScopeListener = new ContextHandler.ContextScopeListener()
{
@Override
public void enterScope(Context context, Request request, Object reason)
{
String cname = findContextName(context);
if (request == null)
log("> ctx=%s %s", cname, reason);
else
{
String rname = findRequestName(request);
if (_renameThread)
{
Thread thread = Thread.currentThread();
thread.setName(String.format("%s#%s", thread.getName(), rname));
}
log("> ctx=%s r=%s %s", cname, rname, reason);
}
}
@Override
public void exitScope(Context context, Request request)
{
String cname = findContextName(context);
if (request == null)
log("< ctx=%s", cname);
else
{
String rname = findRequestName(request);
log("< ctx=%s r=%s", cname, rname);
if (_renameThread)
{
Thread thread = Thread.currentThread();
if (thread.getName().endsWith(rname))
thread.setName(thread.getName().substring(0, thread.getName().length() - rname.length() - 1));
}
}
}
};
}