Estoy trabajando en la API de descanso con arranque de primavera. Necesito registrar todas las solicitudes con parámetros de entrada (con métodos, por ejemplo, GET, POST, etc.), ruta de solicitud, cadena de consulta, método de clase correspondiente de esta solicitud, también respuesta de esta acción, tanto éxito como errores.
Para un ejemplo:
solicitud exitosa:
http://example.com/api/users/1
El registro debe verse más o menos así:
{
HttpStatus: 200,
path: "api/users/1",
method: "GET",
clientIp: "0.0.0.0",
accessToken: "XHGu6as5dajshdgau6i6asdjhgjhg",
method: "UsersController.getUser",
arguments: {
id: 1
},
response: {
user: {
id: 1,
username: "user123",
email: "[email protected]"
}
},
exceptions: []
}
O solicite con error:
http://example.com/api/users/9999
El registro debería ser algo como esto:
{
HttpStatus: 404,
errorCode: 101,
path: "api/users/9999",
method: "GET",
clientIp: "0.0.0.0",
accessToken: "XHGu6as5dajshdgau6i6asdjhgjhg",
method: "UsersController.getUser",
arguments: {
id: 9999
},
returns: {
},
exceptions: [
{
exception: "UserNotFoundException",
message: "User with id 9999 not found",
exceptionId: "adhaskldjaso98d7324kjh989",
stacktrace: ...................
]
}
Deseo que Solicitud / Respuesta sea una entidad única, con información personalizada relacionada con esta entidad, tanto en casos exitosos como de error.
¿Cuál es la mejor práctica en primavera para lograr esto, puede ser con filtros? En caso afirmativo, ¿puede dar un ejemplo concreto?
(He jugado con @ControllerAdvice y @ExceptionHandler, pero como mencioné, necesito manejar todas las solicitudes de éxito y error en un solo lugar (y un solo registro)).
fuente
HandlerInterceptor
pero eso puede no funcionar bien con el registro de la respuesta como se menciona en la respuesta: concretepage.com/spring/spring-mvc/… - HandlerInterceptor tiene acceso al método (método: "UsersController.getUser") sin embargo. Eso no se conoce en un filtro de servlet.LogClass{ getRequestAndSaveIt()} Gson.toJson(LogClass)
como pseudocódigoRespuestas:
No escriba interceptores, filtros, componentes, aspectos, etc., este es un problema muy común y se ha resuelto muchas veces.
Spring Boot tiene un módulo llamado Actuator , que proporciona el registro de solicitudes HTTP fuera de la caja. Hay un punto final asignado a
/trace
(SB1.x) o/actuator/httptrace
(SB2.0 +) que le mostrará las últimas 100 solicitudes HTTP. Puede personalizarlo para registrar cada solicitud o escribir en una base de datos.Para obtener los puntos finales que desea, necesitará la dependencia spring-boot-starter-actuator, y también para "incluir en la lista blanca" los puntos finales que está buscando, y posiblemente configurar o deshabilitar la seguridad.
Además, ¿dónde se ejecutará esta aplicación? ¿Usarás un PaaS? Los proveedores de alojamiento, Heroku, por ejemplo, proporcionan el registro de solicitudes como parte de su servicio y no es necesario que realice ninguna codificación.
fuente
Spring ya proporciona un filtro que hace este trabajo. Agregue el siguiente bean a su configuración
No olvide cambiar el nivel de registro de
org.springframework.web.filter.CommonsRequestLoggingFilter
aDEBUG
.fuente
Podría usarlo
javax.servlet.Filter
si no hubiera un requisito para registrar el método java que se ejecutó.Pero con este requisito que tiene que acceder a información almacenada en
handlerMapping
deDispatcherServlet
. Dicho esto, puede anularDispatcherServlet
para lograr el registro del par de solicitud / respuesta.A continuación se muestra un ejemplo de idea que se puede mejorar y adoptar según sus necesidades.
HandlerExecutionChain
- contiene la información sobre el manejador de solicitudes.Luego puede registrar este despachador de la siguiente manera:
Y aquí está la muestra de registros:
ACTUALIZAR
En caso de errores, Spring realiza el manejo automático de errores. Por lo tanto,
BasicErrorController#error
se muestra como manejador de solicitudes. Si desea conservar el controlador de solicitud original, puede anular este comportamientospring-webmvc-4.2.5.RELEASE-sources.jar!/org/springframework/web/servlet/DispatcherServlet.java:971
antes de que#processDispatchResult
se llame, para almacenar en caché el controlador original.fuente
La biblioteca de Logbook está hecha específicamente para registrar solicitudes y respuestas HTTP. Es compatible con Spring Boot utilizando una biblioteca de inicio especial.
Para habilitar el registro en Spring Boot, todo lo que necesita hacer es agregar la biblioteca a las dependencias de su proyecto. Por ejemplo, suponiendo que está utilizando Maven:
Por defecto, la salida de registro se ve así:
Sin embargo, no muestra el nombre de clase que maneja la solicitud. La biblioteca tiene algunas interfaces para escribir registradores personalizados.
fuente
logging.level.org.zalando.logbook=TRACE
a suapplication.properties
(como se indica en elReadme
)Había definido el nivel de inicio de sesión
application.properties
para imprimir solicitudes / respuestas, url del método en el archivo de registroHabía usado Spring Boot.
fuente
Así es como lo hago en reposo de datos de primavera usando
org.springframework.web.util.ContentCachingRequestWrapper
yorg.springframework.web.util.ContentCachingResponseWrapper
fuente
Si no le importa probar Spring AOP, esto es algo que he estado explorando con fines de registro y me funciona bastante bien. Sin embargo, no registrará solicitudes que no hayan sido definidas e intentos fallidos de solicitud.
Agregue estas tres dependencias
Agregue esto a su archivo de configuración xml
<aop:aspectj-autoproxy/>
Cree una anotación que se pueda usar como un punto de corte
Ahora anote todos sus métodos de API de descanso que desea registrar
Ahora al Aspecto. escanee por componentes el paquete en el que se encuentra esta clase.
Si desea leer en detalle, lea esto. http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
fuente
Después de agregar actuadores a la aplicación basada en el arranque por resorte, tiene un
/trace
punto final disponible con las últimas solicitudes de información. Este punto final funciona en función de TraceRepository y la implementación predeterminada es InMemoryTraceRepository que guarda las últimas 100 llamadas. Puede cambiar esto implementando esta interfaz usted mismo y ponerla a disposición como Spring Bean. Por ejemplo, para registrar todas las solicitudes de registro (y aún usar la implementación predeterminada como almacenamiento básico para servir información en el/trace
punto final) Estoy usando este tipo de implementación:Este
traceInfo
mapa contiene información básica sobre solicitud y respuesta en este tipo de formulario:{method=GET, path=/api/hello/John, headers={request={host=localhost:8080, user-agent=curl/7.51.0, accept=*/*}, response={X-Application-Context=application, Content-Type=text/plain;charset=UTF-8, Content-Length=10, Date=Wed, 29 Mar 2017 20:41:21 GMT, status=200}}}
. No hay contenido de respuesta aquí.¡EDITAR!Registro de datos POST
Puede acceder a los datos POST anulando WebRequestTraceFilter , pero no creo que sea una buena idea (por ejemplo, todo el contenido del archivo cargado irá a los registros). Aquí hay un código de muestra, pero no lo use:
fuente
TraceRepository
, ¿cómo podemos acceder a eso?protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
pero no estoy seguro de cuándo se ejecuta este filtro; puede estar en la fase de solicitud, por lo que el cuerpo de respuesta no estará listo allí.Este código funciona para mí en una aplicación Spring Boot, solo regístralo como filtro
fuente
Actualmente Spring Boot tiene la función Actuador para obtener los registros de solicitudes y respuestas.
Pero también puede obtener los registros utilizando Aspect (AOP).
Aspecto que ofrece con anotaciones como:
@Before
,@AfterReturning
,@AfterThrowing
etc.@Before
registra la solicitud,@AfterReturning
registra la respuesta y@AfterThrowing
registra el mensaje de error. Es posible que no necesite el registro de todos los puntos finales, por lo que puede aplicar algunos filtros en los paquetes.Aquí hay algunos ejemplos :
A petición:
Aquí
@Before("within(your.package.where.endpoints.are..*)")
tiene la ruta del paquete. Todos los puntos finales dentro de este paquete generarán el registro.Para respuesta:
Aquí
@AfterReturning("within(your.package.where.endpoints.are..*)")
tiene la ruta del paquete. Todos los puntos finales dentro de este paquete generarán el registro. TambiénObject returnValue
contiene la respuesta.Por excepción:
Aquí
@AfterThrowing(pointcut = ("within(your.package.where.endpoints.are..*)"), throwing = "e")
tiene la ruta del paquete. Todos los puntos finales dentro de este paquete generarán el registro. tambiénException e
contiene la respuesta de error.Aquí está el código completo:
Aquí, usando
@ConditionalOnExpression("${endpoint.aspect.enabled:true}")
usted puede habilitar / deshabilitar el registro. solo agregueendpoint.aspect.enabled:true
alapplication.property
y controlar el registroMás información sobre la visita de AOP aquí:
Muelles de primavera sobre AOP
Artículo de muestra sobre AOP
fuente
new ObjectMapper()
es caro, mejor comparte un mapeador para todosAquí mi solución (Spring 2.0.x)
Agregue la dependencia de Maven:
Edite application.properties y agregue la siguiente línea:
Una vez que se inicia su aplicación de arranque de primavera, puede rastrear las últimas 100 solicitudes http llamando a esta url: http: // localhost: 8070 / actuator / httptrace
fuente
También puede configurar un interceptor Spring personalizado
HandlerInterceptorAdapter
para una implementación simplificada de interceptores pre-solo / post-solo:Luego, registra tantos interceptores como desee:
Nota: tal como lo indicó @Robert , debe prestar atención a las implementaciones específicas y a las aplicaciones que utiliza.
HttpServletRequest
HttpServletResponse
Por ejemplo, para las aplicaciones que usan
ShallowEtagHeaderFilter
, la implementación de la respuesta sería aContentCachingResponseWrapper
, por lo que tendría:fuente
La respuesta de @Hahn requirió un poco de modificación para que funcionara para mí, pero es, con mucho, la cosa más personalizable que pude obtener.
No funcionó para mí, probablemente porque también tengo un HandlerInterceptorAdapter [??] pero recibí una mala respuesta del servidor en esa versión. Aquí está mi modificación.
fuente
Si alguien aún lo necesita aquí, es una implementación simple con Spring HttpTrace Actuator. Pero como le han dicho a Upper, no registra cuerpos.
fuente
Consulte el siguiente enlace para obtener la respuesta real https://gist.github.com/int128/e47217bebdb4c402b2ffa7cc199307ba
Si se realizan algunos cambios en la solución mencionada anteriormente, la solicitud y la respuesta también se registrarán en la consola y en el archivo si el nivel del registrador es información. podemos imprimir en consola o archivo.
Salida en archivo:
fuente
Si solo ve parte de la carga útil de su solicitud, debe llamar a la
setMaxPayloadLength
función, ya que por defecto muestra solo 50 caracteres en el cuerpo de la solicitud. Además, establecersetIncludeHeaders
en falso es una buena idea si no desea registrar sus encabezados de autenticación.fuente
Si usa Tomcat en su aplicación de arranque, aquí está
org.apache.catalina.filters.RequestDumperFilter
en una ruta de clase para usted. (pero no le proporcionará "con excepciones en un solo lugar").fuente
el código pegado a continuación funciona con mis pruebas y se puede descargar desde mi [proyecto github] [1], compartiéndolo después de aplicar una solución basada en eso en un proyecto de producción.
fuente
Para registrar todas las solicitudes con parámetros y cuerpo de entrada, podemos usar filtros e interceptores . Pero al usar un filtro o interceptor, no podemos imprimir el cuerpo de la solicitud varias veces. La mejor manera es que podemos usar spring-AOP. Al usar esto, podemos desacoplar el mecanismo de registro de la aplicación. AOP se puede utilizar para registrar la entrada y salida de cada método en la aplicación.
Mi solución es:
}
fuente
Si tiene configurado el servidor de configuración de arranque de Spring, simplemente habilite el registrador de depuración para la clase:
Http11InputBuffer.Http11InputBuffer.java
Debugs registrará todas las solicitudes y respuestas para cada solicitud
fuente
Para registrar solicitudes que resultan en 400 solamente:
fuente