Skip to content

Commit

Permalink
Issue #5032 - More work towards wrapper based extensible ServletContext
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 21, 2020
1 parent 344cdf5 commit 1e6c168
Show file tree
Hide file tree
Showing 16 changed files with 962 additions and 35 deletions.
62 changes: 62 additions & 0 deletions jetty-metrics/pom.xml
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.4.32-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-metrics</artifactId>
<name>Jetty :: Metrics</name>
<description>Jetty Metrics</description>
<url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.metrics</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>tests</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.metrics.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,90 @@
//
// ========================================================================
// Copyright (c) 1995-2020 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.metrics;

import java.io.IOException;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.eclipse.jetty.servlet.FilterHolder;

public class MetricsFilterWrapper extends FilterHolder.WrapperFilter
{
private final ServletMetricsListener metricsListener;

public MetricsFilterWrapper(Filter filter, ServletMetricsListener metricsListener)
{
super(filter);
this.metricsListener = metricsListener;
}

@Override
public void init(FilterConfig filterConfig) throws ServletException
{
ServletContext servletContext = filterConfig.getServletContext();
Filter delegate = getWrappedFilter();
long start = System.nanoTime();
try
{
metricsListener.onFilterStarting(servletContext, delegate);
this.getWrappedFilter().init(filterConfig);
}
finally
{
long end = System.nanoTime();
long dur = end - start;
metricsListener.onFilterReady(servletContext, delegate, Duration.of(dur, ChronoUnit.NANOS));
}
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
ServletContext servletContext = request.getServletContext();
Filter delegate = getWrappedFilter();
long start = System.nanoTime();
try
{
metricsListener.onFilterEnter(servletContext, delegate, request);
delegate.doFilter(request, response, chain);
long end = System.nanoTime();
long dur = end - start;
metricsListener.onFilterExit(servletContext, delegate, request, Duration.of(dur, ChronoUnit.NANOS), null);
}
catch (Throwable cause)
{
long end = System.nanoTime();
long dur = end - start;
metricsListener.onFilterExit(servletContext, delegate, request, Duration.of(dur, ChronoUnit.NANOS), cause);
throw cause;
}
}

@Override
public void destroy()
{
}
}
@@ -0,0 +1,91 @@
//
// ========================================================================
// Copyright (c) 1995-2020 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.metrics;

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

import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ListenerHolder;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

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

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

@Override
public EventListener wrapEventListener(EventListener listener)
{
LOG.info("wrapEventListener({})", listener);
return listener;
}

@Override
public Filter wrapFilter(Filter filter)
{
LOG.info("wrapFilter({})", filter);
Filter unwrapped = filter;
while (unwrapped instanceof FilterHolder.WrapperFilter)
{
if (unwrapped instanceof MetricsFilterWrapper)
{
// Are we already wrapped somewhere along the line?
return unwrapped;
}
// Unwrap
unwrapped = ((FilterHolder.WrapperFilter)unwrapped).getWrappedFilter();
}

return new MetricsFilterWrapper(filter, metricsListener);
}

@Override
public Servlet wrapServlet(Servlet servlet)
{
LOG.info("wrapServlet({})", servlet);
Servlet unwrapped = servlet;
while (unwrapped instanceof ServletHolder.WrapperServlet)
{
if (unwrapped instanceof MetricsServletWrapper)
{
// Are we already wrapped somewhere along the line?
return unwrapped;
}
// Unwrap
unwrapped = ((ServletHolder.WrapperServlet)unwrapped).getWrappedServlet();
}

return new MetricsServletWrapper(servlet, metricsListener);
}
}
@@ -0,0 +1,91 @@
//
// ========================================================================
// Copyright (c) 1995-2020 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.metrics;

import java.io.IOException;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Objects;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.eclipse.jetty.servlet.ServletHolder;

public class MetricsServletWrapper extends ServletHolder.WrapperServlet
{
private final ServletMetricsListener metricsListener;

public MetricsServletWrapper(Servlet servlet, ServletMetricsListener metricsListener)
{
super(servlet);
this.metricsListener = metricsListener;
}

/**
* Entry point for {@link ServletHolder#initialize()}
*/
@Override
public void init(ServletConfig config) throws ServletException
{
ServletContext servletContext = config.getServletContext();
Servlet delegate = getWrappedServlet();
long start = System.nanoTime();
try
{
metricsListener.onServletStarting(servletContext, delegate);
delegate.init(config);
}
finally
{
long end = System.nanoTime();
long dur = end - start;
metricsListener.onServletReady(servletContext, delegate, Duration.of(dur, ChronoUnit.NANOS));
}
}

/**
* Entry point for all Servlet requests
*/
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
ServletContext servletContext = req.getServletContext();
Servlet delegate = Objects.requireNonNull(getWrappedServlet());
long start = System.nanoTime();
try
{
metricsListener.onServletEnter(servletContext, delegate, req);
delegate.service(req, res);
long end = System.nanoTime();
long dur = end - start;
metricsListener.onServletExit(servletContext, delegate, req, Duration.of(dur, ChronoUnit.NANOS), null);
}
catch (Throwable cause)
{
long end = System.nanoTime();
long dur = end - start;
metricsListener.onServletExit(servletContext, delegate, req, Duration.of(dur, ChronoUnit.NANOS), cause);
throw cause;
}
}
}
@@ -0,0 +1,23 @@
//
// ========================================================================
// Copyright (c) 1995-2020 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.metrics;

public interface MetricsWrapper
{
}

0 comments on commit 1e6c168

Please sign in to comment.