Skip to content

Commit

Permalink
Issue #5032 - More work on events for context start/ready
Browse files Browse the repository at this point in the history
Signed-off-by: Joakim Erdfelt <joakim.erdfelt@gmail.com>
  • Loading branch information
joakime committed Aug 26, 2020
1 parent 5310d35 commit d35d676
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 7 deletions.
Expand Up @@ -19,31 +19,116 @@
package org.eclipse.jetty.metrics;

import java.util.EventListener;
import java.util.UUID;
import javax.servlet.Filter;
import javax.servlet.Servlet;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ListenerHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.WebAppContext;

public class MetricsHandler extends ContainerLifeCycle
implements ServletHolder.WrapperFunction,
FilterHolder.WrapperFunction,
ListenerHolder.WrapperFunction,
HttpChannel.Listener
HttpChannel.Listener,
LifeCycle.Listener
{
private static final Logger LOG = Log.getLogger(MetricsHandler.class);
public static final String ATTR_REQUEST_ID = MetricsHandler.class.getName() + ".requestId";
private final ServletMetricsListener metricsListener;

public MetricsHandler(ServletMetricsListener metricsListener)
{
this.metricsListener = metricsListener;
}

public void addToAllConnectors(Server server)
{
for (Connector connector : server.getConnectors())
{
if (connector instanceof ServerConnector)
{
connector.addBean(this);
}
}
}

public void addToContext(ServletContextHandler context)
{
context.addBean(this);
context.addLifeCycleListener(this);
}

@Override
public void lifeCycleStarting(LifeCycle event)
{
if (event instanceof WebAppContext)
{
WebAppContext webAppContext = (WebAppContext)event;
if (metricsListener instanceof WebAppMetricsListener)
{
((WebAppMetricsListener)metricsListener).onWebAppStarting(webAppContext);
}
}
if (event instanceof ServletContextHandler)
{
ServletContextHandler contextHandler = (ServletContextHandler)event;
metricsListener.onServletContextStarting(contextHandler.getServletContext());
}
}

@Override
public void lifeCycleStarted(LifeCycle event)
{
if (event instanceof WebAppContext)
{
WebAppContext webAppContext = (WebAppContext)event;
if (metricsListener instanceof WebAppMetricsListener)
{
((WebAppMetricsListener)metricsListener).onWebAppReady(webAppContext);
}
}
if (event instanceof ServletContextHandler)
{
ServletContextHandler contextHandler = (ServletContextHandler)event;
metricsListener.onServletContextReady(contextHandler.getServletContext());
}
}

@Override
public void lifeCycleFailure(LifeCycle event, Throwable cause)
{
}

@Override
public void lifeCycleStopping(LifeCycle event)
{
}

@Override
public void lifeCycleStopped(LifeCycle event)
{
}

@Override
public void onRequestBegin(Request request)
{
String uniqId = UUID.randomUUID().toString();
request.setAttribute(ATTR_REQUEST_ID, uniqId);
}

@Override
public EventListener wrapEventListener(EventListener listener)
{
Expand All @@ -58,10 +143,11 @@ public Filter wrapFilter(Filter filter)
Filter unwrapped = filter;
while (unwrapped instanceof FilterHolder.WrapperFilter)
{
// Are we already wrapped somewhere along the line?
if (unwrapped instanceof MetricsFilterWrapper)
{
// Are we already wrapped somewhere along the line?
return unwrapped;
// If so, we are done. no need to wrap again.
return filter;
}
// Unwrap
unwrapped = ((FilterHolder.WrapperFilter)unwrapped).getWrappedFilter();
Expand All @@ -77,10 +163,11 @@ public Servlet wrapServlet(Servlet servlet)
Servlet unwrapped = servlet;
while (unwrapped instanceof ServletHolder.WrapperServlet)
{
// Are we already wrapped somewhere along the line?
if (unwrapped instanceof MetricsServletWrapper)
{
// Are we already wrapped somewhere along the line?
return unwrapped;
// If so, we are done. no need to wrap again.
return servlet;
}
// Unwrap
unwrapped = ((ServletHolder.WrapperServlet)unwrapped).getWrappedServlet();
Expand Down
Expand Up @@ -66,8 +66,7 @@ enum ConfigurationStep
* </p>
*
* @param context the specific context that was started / initialized
* @param duration the duration for this context's startup
* @see #onServletContextReady(ServletContext)
*/
void onWebAppReady(WebAppContext context, Duration duration);
void onWebAppReady(WebAppContext context);
}
@@ -0,0 +1,28 @@
package org.eclipse.jetty.metrics;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FooFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig)
{
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
chain.doFilter(request, response);
}

@Override
public void destroy()
{
}
}
Expand Up @@ -19,7 +19,9 @@
package org.eclipse.jetty.metrics;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import javax.servlet.DispatcherType;

import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
Expand Down Expand Up @@ -70,18 +72,56 @@ public void testSimpleServlet() throws Exception
contextHandler.addBean(metricsHandler);
contextHandler.addServlet(HelloServlet.class, "/hello");

metricsHandler.addToAllConnectors(server);
metricsHandler.addToContext(contextHandler);
server.setHandler(contextHandler);
server.start();

ContentResponse response = client.GET(server.getURI().resolve("/hello"));
assertThat("Response.status", response.getStatus(), is(HttpStatus.OK_200));

List<String> expectedEvents = new ArrayList<>();
expectedEvents.add("onServletContextStarting()");
expectedEvents.add("onServletContextReady()");
expectedEvents.add("onServletStarting()");
expectedEvents.add("onServletReady()");
expectedEvents.add("onServletEnter()");
expectedEvents.add("onServletExit()");

assertThat("Metrics Events Count", captureListener.events.size(), is(expectedEvents.size()));
}

@Test
public void testSimpleFilterAndServlet() throws Exception
{
ServletMetricsCaptureListener captureListener = new ServletMetricsCaptureListener();
MetricsHandler metricsHandler = new MetricsHandler(captureListener);

ServletContextHandler contextHandler = new ServletContextHandler();
contextHandler.setContextPath("/");
contextHandler.addServlet(HelloServlet.class, "/hello");
contextHandler.addFilter(FooFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));

metricsHandler.addToAllConnectors(server);
metricsHandler.addToContext(contextHandler);
server.setHandler(contextHandler);
server.start();

ContentResponse response = client.GET(server.getURI().resolve("/hello"));
assertThat("Response.status", response.getStatus(), is(HttpStatus.OK_200));

List<String> expectedEvents = new ArrayList<>();
expectedEvents.add("onServletContextStarting()");
expectedEvents.add("onFilterStarting()");
expectedEvents.add("onFilterReady()");
expectedEvents.add("onServletContextReady()");
expectedEvents.add("onServletStarting()");
expectedEvents.add("onServletReady()");
expectedEvents.add("onFilterEnter()");
expectedEvents.add("onServletEnter()");
expectedEvents.add("onServletExit()");
expectedEvents.add("onFilterExit()");

assertThat("Metrics Events Count", captureListener.events.size(), is(expectedEvents.size()));
}
}

0 comments on commit d35d676

Please sign in to comment.