-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #41 from whitingjr/add-jfr-events
Add Java Flight Recorder event for JaxRS requests.
- Loading branch information
Showing
5 changed files
with
240 additions
and
0 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
src/main/java/org/commonjava/util/gateway/exception/mapper/UnhandledThrowableHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.commonjava.util.gateway.exception.mapper; | ||
|
||
import javax.ws.rs.core.MediaType; | ||
import javax.ws.rs.core.Response; | ||
import javax.ws.rs.ext.ExceptionMapper; | ||
import javax.ws.rs.ext.Provider; | ||
|
||
import org.apache.commons.lang3.exception.ExceptionUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* This default mapper allows any exception to be captured ensuring a ResponseContextFilter is always called. | ||
*/ | ||
@Provider | ||
public class UnhandledThrowableHandler | ||
implements ExceptionMapper<Throwable>//, RestProvider | ||
{ | ||
public Response toResponse( Throwable exception ) | ||
{ | ||
Logger logger = LoggerFactory.getLogger( getClass() ); | ||
logger.error( "Unhandled exception: " + exception.getMessage(), exception ); | ||
|
||
return Response.status( Response.Status.INTERNAL_SERVER_ERROR ) | ||
.entity( ExceptionUtils.getStackTrace( exception ) ) | ||
.type( MediaType.TEXT_PLAIN ) | ||
.build(); | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
...org/commonjava/util/gateway/exception/mapper/UnhandledWebApplicationExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/** | ||
* Copyright (C) 2011-2021 Red Hat, Inc. (https://github.com/Commonjava/indy) | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.commonjava.util.gateway.exception.mapper; | ||
|
||
import javax.ws.rs.WebApplicationException; | ||
import javax.ws.rs.core.MediaType; | ||
import javax.ws.rs.core.Response; | ||
import javax.ws.rs.ext.ExceptionMapper; | ||
|
||
import org.apache.commons.lang3.exception.ExceptionUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* This WebApplicationException handler will check for a HTTP response status | ||
* code (SC) in the exception and ensure the client will receive the corresponding SC code. | ||
*/ | ||
public class UnhandledWebApplicationExceptionHandler | ||
implements ExceptionMapper<WebApplicationException> | ||
{ | ||
@Override | ||
public Response toResponse( WebApplicationException exception ) | ||
{ | ||
Response response = null; | ||
if ( exception.getResponse() != null && exception.getResponse().getStatusInfo() != null ) | ||
{ | ||
logger.error( "Unhandled exception: " + exception.getMessage(), exception ); | ||
|
||
response = Response.status( exception.getResponse().getStatusInfo() ) | ||
.entity( ExceptionUtils.getStackTrace( exception ) ) | ||
.type( MediaType.TEXT_PLAIN ) | ||
.build(); | ||
} | ||
else | ||
{ | ||
response = new UnhandledThrowableHandler().toResponse( exception ); | ||
} | ||
return response; | ||
} | ||
|
||
private static final Logger logger = LoggerFactory | ||
.getLogger( UnhandledWebApplicationExceptionHandler.class.getName() ); | ||
|
||
} |
94 changes: 94 additions & 0 deletions
94
src/main/java/org/commonjava/util/gateway/metrics/jfr/FlightRecorderFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package org.commonjava.util.gateway.metrics.jfr; | ||
|
||
import java.io.IOException; | ||
|
||
import javax.ws.rs.container.ContainerRequestContext; | ||
import javax.ws.rs.container.ContainerRequestFilter; | ||
import javax.ws.rs.container.ContainerResponseContext; | ||
import javax.ws.rs.container.ContainerResponseFilter; | ||
import javax.ws.rs.ext.Provider; | ||
|
||
import org.commonjava.util.gateway.metrics.jfr.events.JaxRSEvent; | ||
import org.jboss.resteasy.core.ResourceMethodInvoker; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* Purpose of this filter is to generate events for JaxRS calls when profiling is enabled. | ||
* | ||
*/ | ||
@Provider | ||
public class FlightRecorderFilter implements ContainerRequestFilter, ContainerResponseFilter | ||
{ | ||
@Override | ||
public void filter( ContainerRequestContext requestContext ) throws IOException | ||
{ | ||
logger.trace("processing request context"); | ||
final JaxRSEvent event = new JaxRSEvent(); | ||
final boolean isEnabled = event.isEnabled(); | ||
if ( !isEnabled ) | ||
{ | ||
return; | ||
} | ||
event.begin(); | ||
requestContext.setProperty( JaxRSEvent.NAME, event ); | ||
} | ||
|
||
@Override | ||
public void filter( ContainerRequestContext requestContext, ContainerResponseContext responseContext ) | ||
throws IOException | ||
{ | ||
logger.trace("processing response context"); | ||
if ( requestContext == null ) | ||
{ | ||
logger.error( "request context is null" ); | ||
return; | ||
} | ||
Object prop = requestContext.getProperty( JaxRSEvent.NAME ); | ||
if ( prop == null ) | ||
{ | ||
return; | ||
} | ||
JaxRSEvent event = ( JaxRSEvent ) prop; | ||
if ( !event.isEnabled() ) | ||
{ | ||
return; | ||
} | ||
|
||
event.end(); | ||
|
||
if ( event.shouldCommit() ) | ||
{ | ||
event.method = requestContext.getMethod(); | ||
event.mediaType = String.valueOf ( requestContext.getMediaType() ) ; | ||
event.length = requestContext.getLength(); | ||
event.methodFrameName = getMethodName( requestContext ); | ||
event.path = requestContext.getUriInfo().getPath(); | ||
event.responseLength = responseContext.getLength(); | ||
event.status = responseContext.getStatus(); | ||
|
||
event.commit(); | ||
} | ||
} | ||
|
||
private String getMethodName( ContainerRequestContext context ) | ||
{ | ||
Object p = context.getProperty( METHOD_NAME ); | ||
if ( p == null ) | ||
{ | ||
return ""; | ||
} | ||
if ( p instanceof ResourceMethodInvoker ) | ||
{ | ||
ResourceMethodInvoker invoker = (ResourceMethodInvoker) p; | ||
return invoker.getMethod().getName(); | ||
} | ||
else | ||
{ | ||
return ""; | ||
} | ||
} | ||
|
||
private static final String METHOD_NAME = ResourceMethodInvoker.class.getName(); | ||
private static final Logger logger = LoggerFactory.getLogger( FlightRecorderFilter.class.getName() ); | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/org/commonjava/util/gateway/metrics/jfr/FlightRecorderMetrics.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.commonjava.util.gateway.metrics.jfr; | ||
|
||
import javax.enterprise.context.ApplicationScoped; | ||
import javax.enterprise.event.Observes; | ||
|
||
import org.commonjava.util.gateway.metrics.jfr.events.JaxRSEvent; | ||
|
||
import io.quarkus.runtime.StartupEvent; | ||
import jdk.jfr.FlightRecorder; | ||
|
||
@ApplicationScoped | ||
public class FlightRecorderMetrics | ||
{ | ||
public void registerEvents( @Observes StartupEvent e ) | ||
{ | ||
FlightRecorder.register( JaxRSEvent.class ); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/org/commonjava/util/gateway/metrics/jfr/events/JaxRSEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.commonjava.util.gateway.metrics.jfr.events; | ||
|
||
import jdk.jfr.Category; | ||
import jdk.jfr.DataAmount; | ||
import jdk.jfr.Description; | ||
import jdk.jfr.Event; | ||
import jdk.jfr.Label; | ||
import jdk.jfr.Name; | ||
import jdk.jfr.StackTrace; | ||
|
||
@Name ( JaxRSEvent.NAME ) | ||
@Label ( "Invocation" ) | ||
@Category ( "JaxRS" ) | ||
@Description ( "JaxRS invocation event" ) | ||
@StackTrace ( false ) | ||
public class JaxRSEvent extends Event | ||
{ | ||
public static final String NAME = "o.c.u.g.m.j.e.JaxRSEvent"; | ||
|
||
@Label ( "Resource Method" ) | ||
public String method; | ||
|
||
@Label ( "Media type" ) | ||
public String mediaType; | ||
|
||
@Label ( "Java method" ) | ||
public String methodFrameName; | ||
|
||
@Label ( "Path" ) | ||
public String path; | ||
|
||
@Label ( "Request length" ) | ||
@DataAmount | ||
public int length; | ||
|
||
@Label ( "Response length" ) | ||
@DataAmount | ||
public int responseLength; | ||
|
||
@Label ( "Status" ) | ||
public int status; | ||
} |