Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
3565961d
Commit
3565961d
authored
Jan 22, 2018
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rework HTTP exchange tracing and add support for WebFlux
Closes gh-9980
parent
11064b5d
Changes
46
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
2471 additions
and
1031 deletions
+2471
-1031
trace.adoc
...ator-autoconfigure/src/main/asciidoc/endpoints/trace.adoc
+29
-0
index.adoc
...-boot-actuator-autoconfigure/src/main/asciidoc/index.adoc
+1
-0
TraceRepositoryAutoConfiguration.java
...autoconfigure/trace/TraceRepositoryAutoConfiguration.java
+0
-41
TraceAutoConfiguration.java
...tuate/autoconfigure/web/trace/TraceAutoConfiguration.java
+82
-0
TraceEndpointAutoConfiguration.java
...toconfigure/web/trace/TraceEndpointAutoConfiguration.java
+11
-10
TraceProperties.java
...boot/actuate/autoconfigure/web/trace/TraceProperties.java
+8
-7
package-info.java
...rk/boot/actuate/autoconfigure/web/trace/package-info.java
+2
-2
additional-spring-configuration-metadata.json
...es/META-INF/additional-spring-configuration-metadata.json
+15
-6
spring.factories
...utoconfigure/src/main/resources/META-INF/spring.factories
+3
-4
HttpTraceEndpointDocumentationTests.java
...eb/documentation/HttpTraceEndpointDocumentationTests.java
+130
-0
EndpointAutoConfigurationClasses.java
...ure/integrationtest/EndpointAutoConfigurationClasses.java
+1
-1
JmxEndpointIntegrationTests.java
...onfigure/integrationtest/JmxEndpointIntegrationTests.java
+6
-4
WebMvcEndpointExposureIntegrationTests.java
...tegrationtest/WebMvcEndpointExposureIntegrationTests.java
+3
-1
TraceRepositoryAutoConfigurationTests.java
...onfigure/trace/TraceRepositoryAutoConfigurationTests.java
+0
-64
TraceWebFilterAutoConfigurationTests.java
...configure/trace/TraceWebFilterAutoConfigurationTests.java
+0
-113
TraceAutoConfigurationTests.java
.../autoconfigure/web/trace/TraceAutoConfigurationTests.java
+218
-0
TraceEndpointAutoConfigurationTests.java
...figure/web/trace/TraceEndpointAutoConfigurationTests.java
+17
-10
WebRequestTraceFilter.java
...ngframework/boot/actuate/trace/WebRequestTraceFilter.java
+0
-283
HttpExchangeTracer.java
...gframework/boot/actuate/web/trace/HttpExchangeTracer.java
+183
-0
HttpTrace.java
...org/springframework/boot/actuate/web/trace/HttpTrace.java
+192
-0
HttpTraceEndpoint.java
...ngframework/boot/actuate/web/trace/HttpTraceEndpoint.java
+11
-11
HttpTraceRepository.java
...framework/boot/actuate/web/trace/HttpTraceRepository.java
+11
-10
InMemoryHttpTraceRepository.java
...k/boot/actuate/web/trace/InMemoryHttpTraceRepository.java
+7
-9
Include.java
...a/org/springframework/boot/actuate/web/trace/Include.java
+9
-49
TraceableRequest.java
...ingframework/boot/actuate/web/trace/TraceableRequest.java
+56
-0
TraceableResponse.java
...ngframework/boot/actuate/web/trace/TraceableResponse.java
+19
-17
package-info.java
.../springframework/boot/actuate/web/trace/package-info.java
+4
-4
HttpTraceWebFilter.java
...k/boot/actuate/web/trace/reactive/HttpTraceWebFilter.java
+132
-0
ServerWebExchangeTraceableRequest.java
...web/trace/reactive/ServerWebExchangeTraceableRequest.java
+72
-0
TraceableServerHttpResponse.java
...tuate/web/trace/reactive/TraceableServerHttpResponse.java
+50
-0
package-info.java
...amework/boot/actuate/web/trace/reactive/package-info.java
+22
-0
HttpTraceFilter.java
...ework/boot/actuate/web/trace/servlet/HttpTraceFilter.java
+119
-0
TraceableHttpServletRequest.java
...ctuate/web/trace/servlet/TraceableHttpServletRequest.java
+87
-0
TraceableHttpServletResponse.java
...tuate/web/trace/servlet/TraceableHttpServletResponse.java
+59
-0
package-info.java
...ramework/boot/actuate/web/trace/servlet/package-info.java
+22
-0
WebRequestTraceFilterTests.java
...mework/boot/actuate/trace/WebRequestTraceFilterTests.java
+0
-285
HttpExchangeTracerTests.java
...ework/boot/actuate/web/trace/HttpExchangeTracerTests.java
+335
-0
InMemoryTraceRepositoryTests.java
.../boot/actuate/web/trace/InMemoryTraceRepositoryTests.java
+68
-0
TraceEndpointTests.java
...gframework/boot/actuate/web/trace/TraceEndpointTests.java
+51
-0
HttpTraceWebFilterIntegrationTests.java
...eb/trace/reactive/HttpTraceWebFilterIntegrationTests.java
+131
-0
HttpTraceWebFilterTests.java
...t/actuate/web/trace/reactive/HttpTraceWebFilterTests.java
+167
-0
HttpTraceFilterTests.java
.../boot/actuate/web/trace/servlet/HttpTraceFilterTests.java
+129
-0
production-ready-features.adoc
...oot-docs/src/main/asciidoc/production-ready-features.adoc
+4
-61
spring-boot-features.adoc
...ing-boot-docs/src/main/asciidoc/spring-boot-features.adoc
+4
-1
application.properties
...sample-actuator/src/main/resources/application.properties
+1
-3
SampleActuatorApplicationTests.java
.../java/sample/actuator/SampleActuatorApplicationTests.java
+0
-35
No files found.
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/asciidoc/endpoints/trace.adoc
0 → 100644
View file @
3565961d
[[trace]]
= Trace (`trace`)
The `trace` endpoint provides information about HTTP request-response exchanges.
[[trace-retrieving]]
== Retrieving the Traces
To retrieve the traces, make a `GET` request to `/actuator/trace`, as shown in the
following curl-based example:
include::{snippets}trace/curl-request.adoc[]
The resulting response is similar to the following:
include::{snippets}trace/http-response.adoc[]
[[trace-retrieving-response-structure]]
=== Response Structure
The response contains details of the traced HTTP request-response exchanges. The
following table describes the structure of the response:
[cols="2,1,3"]
include::{snippets}trace/response-fields.adoc[]
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/asciidoc/index.adoc
View file @
3565961d
...
@@ -68,3 +68,4 @@ include::endpoints/scheduledtasks.adoc[leveloffset=+1]
...
@@ -68,3 +68,4 @@ include::endpoints/scheduledtasks.adoc[leveloffset=+1]
include::endpoints/sessions.adoc[leveloffset=+1]
include::endpoints/sessions.adoc[leveloffset=+1]
include::endpoints/shutdown.adoc[leveloffset=+1]
include::endpoints/shutdown.adoc[leveloffset=+1]
include::endpoints/threaddump.adoc[leveloffset=+1]
include::endpoints/threaddump.adoc[leveloffset=+1]
include::endpoints/trace.adoc[leveloffset=+1]
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/trace/TraceRepositoryAutoConfiguration.java
deleted
100644 → 0
View file @
11064b5d
/*
* Copyright 2012-2017 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
import
org.springframework.boot.actuate.trace.InMemoryTraceRepository
;
import
org.springframework.boot.actuate.trace.TraceRepository
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link TraceRepository tracing}.
*
* @author Dave Syer
* @since 2.0.0
*/
@Configuration
public
class
TraceRepositoryAutoConfiguration
{
@ConditionalOnMissingBean
(
TraceRepository
.
class
)
@Bean
public
InMemoryTraceRepository
traceRepository
()
{
return
new
InMemoryTraceRepository
();
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/
trace/TraceWebFilter
AutoConfiguration.java
→
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/
web/trace/Trace
AutoConfiguration.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,62 +14,69 @@
...
@@ -14,62 +14,69 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
web
.
trace
;
import
javax.servlet.Servlet
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
javax.servlet.ServletRegistration
;
import
org.springframework.boot.actuate.web.trace.HttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.InMemoryHttpTraceRepository
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.boot.actuate.web.trace.reactive.HttpTraceWebFilter
;
import
org.springframework.boot.actuate.trace.TraceRepository
;
import
org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter
;
import
org.springframework.boot.actuate.trace.WebRequestTraceFilter
;
import
org.springframework.boot.autoconfigure.AutoConfigureAfter
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnClass
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.boot.web.servlet.error.ErrorAttributes
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.web.servlet.DispatcherServlet
;
/**
/**
* {@link EnableAutoConfiguration Auto-configuration} for {@link WebRequestTraceFilter
* {@link EnableAutoConfiguration Auto-configuration} for HTTP tracing.
* tracing}.
*
*
* @author Dave Syer
* @author Dave Syer
* @since 2.0.0
* @since 2.0.0
*/
*/
@Configuration
@Configuration
@ConditionalOnClass
({
Servlet
.
class
,
DispatcherServlet
.
class
,
ServletRegistration
.
class
})
@ConditionalOnWebApplication
@AutoConfigureAfter
(
TraceRepositoryAutoConfiguration
.
class
)
@ConditionalOnProperty
(
prefix
=
"management.trace"
,
name
=
"enabled"
,
matchIfMissing
=
true
)
@ConditionalOnProperty
(
prefix
=
"management.trace.filter"
,
name
=
"enabled"
,
matchIfMissing
=
true
)
@EnableConfigurationProperties
(
TraceProperties
.
class
)
@EnableConfigurationProperties
(
TraceEndpointProperties
.
class
)
public
class
TraceAutoConfiguration
{
public
class
TraceWebFilterAutoConfiguration
{
@Bean
@ConditionalOnMissingBean
(
HttpTraceRepository
.
class
)
public
InMemoryHttpTraceRepository
traceRepository
()
{
return
new
InMemoryHttpTraceRepository
();
}
private
final
TraceRepository
traceRepository
;
@Bean
@ConditionalOnMissingBean
public
HttpExchangeTracer
httpExchangeTracer
(
TraceProperties
traceProperties
)
{
return
new
HttpExchangeTracer
(
traceProperties
.
getInclude
());
}
private
final
TraceEndpointProperties
endpointProperties
;
@ConditionalOnWebApplication
(
type
=
Type
.
SERVLET
)
static
class
ServletTraceFilterConfiguration
{
private
final
ErrorAttributes
errorAttributes
;
@Bean
@ConditionalOnMissingBean
public
HttpTraceFilter
httpTraceFilter
(
HttpTraceRepository
repository
,
HttpExchangeTracer
tracer
)
{
return
new
HttpTraceFilter
(
repository
,
tracer
);
}
public
TraceWebFilterAutoConfiguration
(
TraceRepository
traceRepository
,
TraceEndpointProperties
endpointProperties
,
ObjectProvider
<
ErrorAttributes
>
errorAttributes
)
{
this
.
traceRepository
=
traceRepository
;
this
.
endpointProperties
=
endpointProperties
;
this
.
errorAttributes
=
errorAttributes
.
getIfAvailable
();
}
}
@Bean
@ConditionalOnWebApplication
(
type
=
Type
.
REACTIVE
)
@ConditionalOnMissingBean
static
class
ReactiveTraceFilterConfiguration
{
public
WebRequestTraceFilter
webRequestLoggingFilter
()
{
WebRequestTraceFilter
filter
=
new
WebRequestTraceFilter
(
this
.
traceRepository
,
@Bean
this
.
endpointProperties
.
getInclude
());
@ConditionalOnMissingBean
if
(
this
.
errorAttributes
!=
null
)
{
public
HttpTraceWebFilter
httpTraceWebFilter
(
HttpTraceRepository
repository
,
filter
.
setErrorAttributes
(
this
.
errorAttributes
);
HttpExchangeTracer
tracer
,
TraceProperties
traceProperties
)
{
return
new
HttpTraceWebFilter
(
repository
,
tracer
,
traceProperties
.
getInclude
());
}
}
return
filter
;
}
}
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/trace/TraceEndpointAutoConfiguration.java
→
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/
web/
trace/TraceEndpointAutoConfiguration.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,33 +14,34 @@
...
@@ -14,33 +14,34 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
web
.
trace
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint
;
import
org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint
;
import
org.springframework.boot.actuate.
trace.InMemoryTraceRepository
;
import
org.springframework.boot.actuate.
web.trace.HttpTraceEndpoint
;
import
org.springframework.boot.actuate.
trace.TraceEndpoint
;
import
org.springframework.boot.actuate.
web.trace.HttpTraceRepository
;
import
org.springframework.boot.a
ctuate.trace.TraceRepository
;
import
org.springframework.boot.a
utoconfigure.AutoConfigureAfter
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
/**
/**
* {@link EnableAutoConfiguration Auto-configuration} for the {@link TraceEndpoint}.
* {@link EnableAutoConfiguration Auto-configuration} for the {@link
Http
TraceEndpoint}.
*
*
* @author Phillip Webb
* @author Phillip Webb
* @since 2.0.0
* @since 2.0.0
*/
*/
@Configuration
@Configuration
@AutoConfigureAfter
(
TraceAutoConfiguration
.
class
)
public
class
TraceEndpointAutoConfiguration
{
public
class
TraceEndpointAutoConfiguration
{
@Bean
@Bean
@ConditionalOnBean
(
HttpTraceRepository
.
class
)
@ConditionalOnMissingBean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
@ConditionalOnEnabledEndpoint
public
TraceEndpoint
traceEndpoint
(
ObjectProvider
<
TraceRepository
>
traceRepository
)
{
public
HttpTraceEndpoint
traceEndpoint
(
HttpTraceRepository
traceRepository
)
{
return
new
TraceEndpoint
(
return
new
HttpTraceEndpoint
(
traceRepository
);
traceRepository
.
getIfAvailable
(()
->
new
InMemoryTraceRepository
()));
}
}
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/
trace/TraceEndpoint
Properties.java
→
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/
web/trace/Trace
Properties.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,12 +14,12 @@
...
@@ -14,12 +14,12 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
web
.
trace
;
import
java.util.HashSet
;
import
java.util.HashSet
;
import
java.util.Set
;
import
java.util.Set
;
import
org.springframework.boot.actuate.trace.Include
;
import
org.springframework.boot.actuate.
web.
trace.Include
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
/**
/**
...
@@ -30,14 +30,15 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
...
@@ -30,14 +30,15 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
* @author Venil Noronha
* @author Venil Noronha
* @author Madhura Bhave
* @author Madhura Bhave
* @author Stephane Nicoll
* @author Stephane Nicoll
* @since
1.3
.0
* @since
2.0
.0
*/
*/
@ConfigurationProperties
(
prefix
=
"management.trace"
)
@ConfigurationProperties
(
prefix
=
"management.trace"
)
public
class
Trace
Endpoint
Properties
{
public
class
TraceProperties
{
/**
/**
* Items to be included in the trace. Defaults to request/response headers (including
* Items to be included in the trace. Defaults to request headers (excluding
* cookies) and errors.
* Authorization but including Cookie), response headers (including Set-Cookie), and
* time taken.
*/
*/
private
Set
<
Include
>
include
=
new
HashSet
<>(
Include
.
defaultIncludes
());
private
Set
<
Include
>
include
=
new
HashSet
<>(
Include
.
defaultIncludes
());
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/trace/package-info.java
→
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/
web/
trace/package-info.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -17,4 +17,4 @@
...
@@ -17,4 +17,4 @@
/**
/**
* Auto-configuration for actuator tracing concerns.
* Auto-configuration for actuator tracing concerns.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
web
.
trace
;
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
View file @
3565961d
...
@@ -185,12 +185,6 @@
...
@@ -185,12 +185,6 @@
"name"
:
"management.info.git.mode"
,
"name"
:
"management.info.git.mode"
,
"defaultValue"
:
"simple"
"defaultValue"
:
"simple"
},
},
{
"name"
:
"management.trace.filter.enabled"
,
"type"
:
"java.lang.Boolean"
,
"description"
:
"Whether to enable the trace servlet filter."
,
"defaultValue"
:
true
},
{
{
"name"
:
"management.metrics.binders.jvm.enabled"
,
"name"
:
"management.metrics.binders.jvm.enabled"
,
"type"
:
"java.lang.Boolean"
,
"type"
:
"java.lang.Boolean"
,
...
@@ -239,6 +233,21 @@
...
@@ -239,6 +233,21 @@
"description"
:
"Instrument all available connection factories."
,
"description"
:
"Instrument all available connection factories."
,
"defaultValue"
:
true
"defaultValue"
:
true
},
},
{
"name"
:
"management.trace.enabled"
,
"type"
:
"java.lang.Boolean"
,
"description"
:
"Whether to enable HTTP request-response tracing."
,
"defaultValue"
:
true
},
{
"name"
:
"management.trace.filter.enabled"
,
"type"
:
"java.lang.Boolean"
,
"description"
:
"Whether to enable the trace servlet filter."
,
"deprecation"
:
{
"replacement"
:
"management.trace.enabled"
,
"level"
:
"error"
}
},
{
{
"name"
:
"endpoints.actuator.enabled"
,
"name"
:
"endpoints.actuator.enabled"
,
"type"
:
"java.lang.Boolean"
,
"type"
:
"java.lang.Boolean"
,
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories
View file @
3565961d
...
@@ -39,13 +39,12 @@ org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksEndpoint
...
@@ -39,13 +39,12 @@ org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksEndpoint
org.springframework.boot.actuate.autoconfigure.session.SessionsEndpointAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.session.SessionsEndpointAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.solr.SolrHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.solr.SolrHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.trace.TraceEndpointAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.trace.TraceRepositoryAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.trace.TraceWebFilterAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementContextAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.trace.TraceAutoConfiguration,\
org.springframework.boot.actuate.autoconfigure.web.trace.TraceEndpointAutoConfiguration
org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=\
org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=\
org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration,\
org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration,\
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/HttpTraceEndpointDocumentationTests.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
autoconfigure
.
endpoint
.
web
.
documentation
;
import
java.net.URI
;
import
java.security.Principal
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.EnumSet
;
import
java.util.UUID
;
import
org.junit.Test
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
org.springframework.boot.actuate.web.trace.HttpTrace
;
import
org.springframework.boot.actuate.web.trace.HttpTraceEndpoint
;
import
org.springframework.boot.actuate.web.trace.HttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.Include
;
import
org.springframework.boot.actuate.web.trace.TraceableRequest
;
import
org.springframework.boot.actuate.web.trace.TraceableResponse
;
import
org.springframework.boot.test.mock.mockito.MockBean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.http.HttpHeaders
;
import
org.springframework.restdocs.payload.JsonFieldType
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
springframework
.
restdocs
.
mockmvc
.
MockMvcRestDocumentation
.
document
;
import
static
org
.
springframework
.
restdocs
.
payload
.
PayloadDocumentation
.
fieldWithPath
;
import
static
org
.
springframework
.
restdocs
.
payload
.
PayloadDocumentation
.
responseFields
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
request
.
MockMvcRequestBuilders
.
get
;
import
static
org
.
springframework
.
test
.
web
.
servlet
.
result
.
MockMvcResultMatchers
.
status
;
/**
* Tests for generating documentation describing {@link HttpTraceEndpoint}.
*
* @author Andy Wilkinson
*/
public
class
HttpTraceEndpointDocumentationTests
extends
MockMvcEndpointDocumentationTests
{
@MockBean
private
HttpTraceRepository
repository
;
@Test
public
void
traces
()
throws
Exception
{
TraceableRequest
request
=
mock
(
TraceableRequest
.
class
);
given
(
request
.
getUri
()).
willReturn
(
URI
.
create
(
"https://api.example.com"
));
given
(
request
.
getMethod
()).
willReturn
(
"GET"
);
given
(
request
.
getHeaders
()).
willReturn
(
Collections
.
singletonMap
(
HttpHeaders
.
ACCEPT
,
Arrays
.
asList
(
"application/json"
)));
TraceableResponse
response
=
mock
(
TraceableResponse
.
class
);
given
(
response
.
getStatus
()).
willReturn
(
200
);
given
(
response
.
getHeaders
()).
willReturn
(
Collections
.
singletonMap
(
HttpHeaders
.
CONTENT_TYPE
,
Arrays
.
asList
(
"application/json"
)));
Principal
principal
=
mock
(
Principal
.
class
);
given
(
principal
.
getName
()).
willReturn
(
"alice"
);
HttpExchangeTracer
tracer
=
new
HttpExchangeTracer
(
EnumSet
.
allOf
(
Include
.
class
));
HttpTrace
trace
=
tracer
.
receivedRequest
(
request
);
tracer
.
sendingResponse
(
trace
,
response
,
()
->
principal
,
()
->
UUID
.
randomUUID
().
toString
());
given
(
this
.
repository
.
findAll
()).
willReturn
(
Arrays
.
asList
(
trace
));
this
.
mockMvc
.
perform
(
get
(
"/actuator/trace"
)).
andExpect
(
status
().
isOk
())
.
andDo
(
document
(
"trace"
,
responseFields
(
fieldWithPath
(
"traces"
).
description
(
"An array of traced HTTP request-response exchanges."
),
fieldWithPath
(
"traces.[].timestamp"
).
description
(
"Timestamp of when the traced exchange occurred."
),
fieldWithPath
(
"traces.[].principal"
)
.
description
(
"Principal of the exchange, if any."
)
.
optional
(),
fieldWithPath
(
"traces.[].principal.name"
)
.
description
(
"Name of the principal."
).
optional
(),
fieldWithPath
(
"traces.[].request.method"
)
.
description
(
"HTTP method of the request."
),
fieldWithPath
(
"traces.[].request.remoteAddress"
)
.
description
(
"Remote address from which the request was received, if known."
)
.
optional
().
type
(
JsonFieldType
.
STRING
),
fieldWithPath
(
"traces.[].request.uri"
)
.
description
(
"URI of the request."
),
fieldWithPath
(
"traces.[].request.headers"
).
description
(
"Headers of the request, keyed by header name."
),
fieldWithPath
(
"traces.[].request.headers.*.[]"
)
.
description
(
"Values of the header"
),
fieldWithPath
(
"traces.[].response.status"
)
.
description
(
"Status of the response"
),
fieldWithPath
(
"traces.[].response.headers"
).
description
(
"Headers of the response, keyed by header name."
),
fieldWithPath
(
"traces.[].response.headers.*.[]"
)
.
description
(
"Values of the header"
),
fieldWithPath
(
"traces.[].session"
)
.
description
(
"Session associated with the exchange, if any."
)
.
optional
(),
fieldWithPath
(
"traces.[].session.id"
)
.
description
(
"ID of the session."
),
fieldWithPath
(
"traces.[].timeTaken"
).
description
(
"Time, in milliseconds, taken to handle the exchange."
))));
}
@Configuration
@Import
(
BaseDocumentationConfiguration
.
class
)
static
class
TestConfiguration
{
@Bean
public
HttpTraceEndpoint
httpTraceEndpoint
(
HttpTraceRepository
repository
)
{
return
new
HttpTraceEndpoint
(
repository
);
}
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/EndpointAutoConfigurationClasses.java
View file @
3565961d
...
@@ -28,8 +28,8 @@ import org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointAut
...
@@ -28,8 +28,8 @@ import org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointAut
import
org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.management.ThreadDumpEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.management.ThreadDumpEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.trace.TraceEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.trace.TraceEndpointAutoConfiguration
;
/**
/**
* A list of all endpoint auto-configuration classes for use in tests.
* A list of all endpoint auto-configuration classes for use in tests.
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/JmxEndpointIntegrationTests.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -28,9 +28,10 @@ import org.junit.Test;
...
@@ -28,9 +28,10 @@ import org.junit.Test;
import
org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.trace.TraceAutoConfiguration
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
;
import
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration
;
import
org.springframework.boot.test.context.runner.ApplicationContextRunner
;
import
org.springframework.boot.test.context.runner.
Web
ApplicationContextRunner
;
import
org.springframework.util.StringUtils
;
import
org.springframework.util.StringUtils
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
@@ -43,9 +44,10 @@ import static org.assertj.core.api.Assertions.assertThat;
...
@@ -43,9 +44,10 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
*/
public
class
JmxEndpointIntegrationTests
{
public
class
JmxEndpointIntegrationTests
{
private
final
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
private
final
WebApplicationContextRunner
contextRunner
=
new
Web
ApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
JmxAutoConfiguration
.
class
,
.
withConfiguration
(
AutoConfigurations
.
of
(
JmxAutoConfiguration
.
class
,
EndpointAutoConfiguration
.
class
,
JmxEndpointAutoConfiguration
.
class
))
EndpointAutoConfiguration
.
class
,
JmxEndpointAutoConfiguration
.
class
,
TraceAutoConfiguration
.
class
))
.
withConfiguration
(
.
withConfiguration
(
AutoConfigurations
.
of
(
EndpointAutoConfigurationClasses
.
ALL
));
AutoConfigurations
.
of
(
EndpointAutoConfigurationClasses
.
ALL
));
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/integrationtest/WebMvcEndpointExposureIntegrationTests.java
View file @
3565961d
...
@@ -22,6 +22,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfi
...
@@ -22,6 +22,7 @@ import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfi
import
org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration
;
import
org.springframework.boot.actuate.autoconfigure.web.trace.TraceAutoConfiguration
;
import
org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint
;
import
org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
;
import
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
;
...
@@ -59,7 +60,8 @@ public class WebMvcEndpointExposureIntegrationTests {
...
@@ -59,7 +60,8 @@ public class WebMvcEndpointExposureIntegrationTests {
ManagementContextAutoConfiguration
.
class
,
ManagementContextAutoConfiguration
.
class
,
ServletManagementContextAutoConfiguration
.
class
,
ServletManagementContextAutoConfiguration
.
class
,
ManagementContextAutoConfiguration
.
class
,
ManagementContextAutoConfiguration
.
class
,
ServletManagementContextAutoConfiguration
.
class
))
ServletManagementContextAutoConfiguration
.
class
,
TraceAutoConfiguration
.
class
))
.
withConfiguration
(
.
withConfiguration
(
AutoConfigurations
.
of
(
EndpointAutoConfigurationClasses
.
ALL
))
AutoConfigurations
.
of
(
EndpointAutoConfigurationClasses
.
ALL
))
.
withUserConfiguration
(
CustomMvcEndpoint
.
class
);
.
withUserConfiguration
(
CustomMvcEndpoint
.
class
);
...
...
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/trace/TraceRepositoryAutoConfigurationTests.java
deleted
100644 → 0
View file @
11064b5d
/*
* Copyright 2012-2017 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
import
org.junit.Test
;
import
org.springframework.boot.actuate.trace.InMemoryTraceRepository
;
import
org.springframework.boot.actuate.trace.TraceRepository
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
* Tests for {@link TraceRepositoryAutoConfiguration}.
*
* @author Phillip Webb
*/
public
class
TraceRepositoryAutoConfigurationTests
{
@Test
public
void
configuresInMemoryTraceRepository
()
{
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
TraceRepositoryAutoConfiguration
.
class
);
assertThat
(
context
.
getBean
(
InMemoryTraceRepository
.
class
)).
isNotNull
();
context
.
close
();
}
@Test
public
void
skipsIfRepositoryExists
()
{
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
Config
.
class
,
TraceRepositoryAutoConfiguration
.
class
);
assertThat
(
context
.
getBeansOfType
(
InMemoryTraceRepository
.
class
)).
isEmpty
();
assertThat
(
context
.
getBeansOfType
(
TraceRepository
.
class
)).
hasSize
(
1
);
context
.
close
();
}
@Configuration
public
static
class
Config
{
@Bean
public
TraceRepository
traceRepository
()
{
return
mock
(
TraceRepository
.
class
);
}
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/trace/TraceWebFilterAutoConfigurationTests.java
deleted
100644 → 0
View file @
11064b5d
/*
* Copyright 2012-2017 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
import
java.util.Map
;
import
org.junit.After
;
import
org.junit.Test
;
import
org.springframework.boot.actuate.trace.TraceRepository
;
import
org.springframework.boot.actuate.trace.WebRequestTraceFilter
;
import
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
;
import
org.springframework.boot.test.util.TestPropertyValues
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Tests for {@link TraceWebFilterAutoConfiguration}.
*
* @author Phillip Webb
* @author Stephane Nicoll
*/
public
class
TraceWebFilterAutoConfigurationTests
{
private
AnnotationConfigApplicationContext
context
;
@After
public
void
close
()
{
if
(
this
.
context
!=
null
)
{
this
.
context
.
close
();
}
}
@Test
public
void
configureFilter
()
{
load
();
assertThat
(
this
.
context
.
getBean
(
WebRequestTraceFilter
.
class
)).
isNotNull
();
}
@Test
public
void
overrideTraceFilter
()
{
load
(
CustomTraceFilterConfig
.
class
);
WebRequestTraceFilter
filter
=
this
.
context
.
getBean
(
WebRequestTraceFilter
.
class
);
assertThat
(
filter
).
isInstanceOf
(
TestWebRequestTraceFilter
.
class
);
}
@Test
public
void
skipsFilterIfPropertyDisabled
()
{
load
(
"management.trace.filter.enabled:false"
);
assertThat
(
this
.
context
.
getBeansOfType
(
WebRequestTraceFilter
.
class
).
size
())
.
isEqualTo
(
0
);
}
private
void
load
(
String
...
environment
)
{
load
(
null
,
environment
);
}
private
void
load
(
Class
<?>
config
,
String
...
environment
)
{
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
();
TestPropertyValues
.
of
(
environment
).
applyTo
(
context
);
if
(
config
!=
null
)
{
context
.
register
(
config
);
}
context
.
register
(
PropertyPlaceholderAutoConfiguration
.
class
,
TraceRepositoryAutoConfiguration
.
class
,
TraceWebFilterAutoConfiguration
.
class
);
context
.
refresh
();
this
.
context
=
context
;
}
@Configuration
static
class
CustomTraceFilterConfig
{
@Bean
public
TestWebRequestTraceFilter
testWebRequestTraceFilter
(
TraceRepository
repository
,
TraceEndpointProperties
properties
)
{
return
new
TestWebRequestTraceFilter
(
repository
,
properties
);
}
}
static
class
TestWebRequestTraceFilter
extends
WebRequestTraceFilter
{
TestWebRequestTraceFilter
(
TraceRepository
repository
,
TraceEndpointProperties
properties
)
{
super
(
repository
,
properties
.
getInclude
());
}
@Override
protected
void
postProcessRequestHeaders
(
Map
<
String
,
Object
>
headers
)
{
headers
.
clear
();
}
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/web/trace/TraceAutoConfigurationTests.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
autoconfigure
.
web
.
trace
;
import
java.util.List
;
import
java.util.Set
;
import
org.junit.Test
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
org.springframework.boot.actuate.web.trace.HttpTrace
;
import
org.springframework.boot.actuate.web.trace.HttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.InMemoryHttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.Include
;
import
org.springframework.boot.actuate.web.trace.reactive.HttpTraceWebFilter
;
import
org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner
;
import
org.springframework.boot.test.context.runner.WebApplicationContextRunner
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Tests for {@link TraceAutoConfiguration}.
*
* @author Andy Wilkinson
*/
public
class
TraceAutoConfigurationTests
{
@Test
public
void
configuresRepository
()
{
new
WebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
run
((
context
)
->
assertThat
(
context
)
.
hasSingleBean
(
InMemoryHttpTraceRepository
.
class
));
}
@Test
public
void
usesUserProvidedRepository
()
{
new
WebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
withUserConfiguration
(
CustomRepositoryConfiguration
.
class
)
.
run
((
context
)
->
{
assertThat
(
context
).
hasSingleBean
(
HttpTraceRepository
.
class
);
assertThat
(
context
.
getBean
(
HttpTraceRepository
.
class
))
.
isInstanceOf
(
CustomHttpTraceRepository
.
class
);
});
}
@Test
public
void
configuresTracer
()
{
new
WebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
run
((
context
)
->
assertThat
(
context
)
.
hasSingleBean
(
HttpExchangeTracer
.
class
));
}
@Test
public
void
usesUserProvidedTracer
()
{
new
WebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
withUserConfiguration
(
CustomTracerConfiguration
.
class
).
run
((
context
)
->
{
assertThat
(
context
).
hasSingleBean
(
HttpExchangeTracer
.
class
);
assertThat
(
context
.
getBean
(
HttpExchangeTracer
.
class
))
.
isInstanceOf
(
CustomHttpExchangeTracer
.
class
);
});
}
@Test
public
void
configuresWebFilter
()
{
new
ReactiveWebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
run
((
context
)
->
assertThat
(
context
)
.
hasSingleBean
(
HttpTraceWebFilter
.
class
));
}
@Test
public
void
usesUserProvidedWebFilter
()
{
new
ReactiveWebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
withUserConfiguration
(
CustomWebFilterConfiguration
.
class
)
.
run
((
context
)
->
{
assertThat
(
context
).
hasSingleBean
(
HttpTraceWebFilter
.
class
);
assertThat
(
context
.
getBean
(
HttpTraceWebFilter
.
class
))
.
isInstanceOf
(
CustomHttpTraceWebFilter
.
class
);
});
}
@Test
public
void
configuresServletFilter
()
{
new
WebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
run
((
context
)
->
assertThat
(
context
)
.
hasSingleBean
(
HttpTraceFilter
.
class
));
}
@Test
public
void
usesUserProvidedServletFilter
()
{
new
WebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
withUserConfiguration
(
CustomFilterConfiguration
.
class
).
run
((
context
)
->
{
assertThat
(
context
).
hasSingleBean
(
HttpTraceFilter
.
class
);
assertThat
(
context
.
getBean
(
HttpTraceFilter
.
class
))
.
isInstanceOf
(
CustomHttpTraceFilter
.
class
);
});
}
@Test
public
void
backsOffWhenDisabled
()
{
new
WebApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
))
.
withPropertyValues
(
"management.trace.enabled=false"
)
.
run
((
context
)
->
assertThat
(
context
)
.
doesNotHaveBean
(
InMemoryHttpTraceRepository
.
class
)
.
doesNotHaveBean
(
HttpExchangeTracer
.
class
)
.
doesNotHaveBean
(
HttpTraceFilter
.
class
));
}
private
static
class
CustomHttpTraceRepository
implements
HttpTraceRepository
{
@Override
public
List
<
HttpTrace
>
findAll
()
{
return
null
;
}
@Override
public
void
add
(
HttpTrace
trace
)
{
}
}
@Configuration
static
class
CustomRepositoryConfiguration
{
@Bean
public
CustomHttpTraceRepository
customRepository
()
{
return
new
CustomHttpTraceRepository
();
}
}
private
static
final
class
CustomHttpExchangeTracer
extends
HttpExchangeTracer
{
private
CustomHttpExchangeTracer
(
Set
<
Include
>
includes
)
{
super
(
includes
);
}
}
@Configuration
static
class
CustomTracerConfiguration
{
@Bean
public
CustomHttpExchangeTracer
customTracer
(
TraceProperties
properties
)
{
return
new
CustomHttpExchangeTracer
(
properties
.
getInclude
());
}
}
private
static
final
class
CustomHttpTraceWebFilter
extends
HttpTraceWebFilter
{
private
CustomHttpTraceWebFilter
(
HttpTraceRepository
repository
,
HttpExchangeTracer
tracer
,
Set
<
Include
>
includes
)
{
super
(
repository
,
tracer
,
includes
);
}
}
@Configuration
static
class
CustomWebFilterConfiguration
{
@Bean
public
CustomHttpTraceWebFilter
customWebFilter
(
HttpTraceRepository
repository
,
HttpExchangeTracer
tracer
,
TraceProperties
properties
)
{
return
new
CustomHttpTraceWebFilter
(
repository
,
tracer
,
properties
.
getInclude
());
}
}
private
static
final
class
CustomHttpTraceFilter
extends
HttpTraceFilter
{
private
CustomHttpTraceFilter
(
HttpTraceRepository
repository
,
HttpExchangeTracer
tracer
)
{
super
(
repository
,
tracer
);
}
}
@Configuration
static
class
CustomFilterConfiguration
{
@Bean
public
CustomHttpTraceFilter
customWebFilter
(
HttpTraceRepository
repository
,
HttpExchangeTracer
tracer
)
{
return
new
CustomHttpTraceFilter
(
repository
,
tracer
);
}
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/trace/TraceEndpointAutoConfigurationTests.java
→
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/
web/
trace/TraceEndpointAutoConfigurationTests.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,13 +14,13 @@
...
@@ -14,13 +14,13 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
web
.
trace
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.springframework.boot.actuate.
trace.
TraceEndpoint
;
import
org.springframework.boot.actuate.
web.trace.Http
TraceEndpoint
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.test.context.runner.ApplicationContextRunner
;
import
org.springframework.boot.test.context.runner.
Web
ApplicationContextRunner
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
@@ -31,21 +31,28 @@ import static org.assertj.core.api.Assertions.assertThat;
...
@@ -31,21 +31,28 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
*/
public
class
TraceEndpointAutoConfigurationTests
{
public
class
TraceEndpointAutoConfigurationTests
{
private
final
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
private
final
WebApplicationContextRunner
contextRunner
=
new
Web
ApplicationContextRunner
()
.
withConfiguration
(
.
withConfiguration
(
AutoConfigurations
.
of
(
TraceAutoConfiguration
.
class
,
AutoConfigurations
.
of
(
TraceEndpointAutoConfiguration
.
class
));
TraceEndpointAutoConfiguration
.
class
));
@Test
@Test
public
void
runShouldHaveEndpointBean
()
{
public
void
runShouldHaveEndpointBean
()
{
this
.
contextRunner
this
.
contextRunner
.
run
(
.
run
((
context
)
->
assertThat
(
context
).
hasSingleBean
(
TraceEndpoint
.
class
));
(
context
)
->
assertThat
(
context
).
hasSingleBean
(
Http
TraceEndpoint
.
class
));
}
}
@Test
@Test
public
void
runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean
()
{
public
void
runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean
()
{
this
.
contextRunner
.
withPropertyValues
(
"management.endpoint.trace.enabled:false"
)
this
.
contextRunner
.
withPropertyValues
(
"management.endpoint.trace.enabled:false"
)
.
run
((
context
)
->
assertThat
(
context
)
.
run
((
context
)
->
assertThat
(
context
)
.
doesNotHaveBean
(
TraceEndpoint
.
class
));
.
doesNotHaveBean
(
HttpTraceEndpoint
.
class
));
}
@Test
public
void
endpointBacksOffWhenRepositoryIsNotAvailable
()
{
this
.
contextRunner
.
withPropertyValues
(
"management.trace.enabled:false"
)
.
run
((
context
)
->
assertThat
(
context
)
.
doesNotHaveBean
(
HttpTraceEndpoint
.
class
));
}
}
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/trace/WebRequestTraceFilter.java
deleted
100644 → 0
View file @
11064b5d
/*
* Copyright 2012-2017 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
trace
;
import
java.io.IOException
;
import
java.security.Principal
;
import
java.util.Collections
;
import
java.util.Enumeration
;
import
java.util.HashSet
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.TimeUnit
;
import
javax.servlet.Filter
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponseWrapper
;
import
javax.servlet.http.HttpSession
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.boot.web.servlet.error.ErrorAttributes
;
import
org.springframework.core.Ordered
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.context.request.ServletWebRequest
;
import
org.springframework.web.filter.OncePerRequestFilter
;
/**
* Servlet {@link Filter} that logs all requests to a {@link TraceRepository}.
*
* @author Dave Syer
* @author Wallace Wadge
* @author Andy Wilkinson
* @author Venil Noronha
* @author Madhura Bhave
*/
public
class
WebRequestTraceFilter
extends
OncePerRequestFilter
implements
Ordered
{
private
static
final
Log
logger
=
LogFactory
.
getLog
(
WebRequestTraceFilter
.
class
);
private
boolean
dumpRequests
=
false
;
// Not LOWEST_PRECEDENCE, but near the end, so it has a good chance of catching all
// enriched headers, but users can add stuff after this if they want to
private
int
order
=
Ordered
.
LOWEST_PRECEDENCE
-
10
;
private
final
TraceRepository
repository
;
private
ErrorAttributes
errorAttributes
;
private
final
Set
<
Include
>
includes
;
/**
* Create a new {@link WebRequestTraceFilter} instance.
* @param repository the trace repository
* @param includes the {@link Include} to apply
*/
public
WebRequestTraceFilter
(
TraceRepository
repository
,
Set
<
Include
>
includes
)
{
this
.
repository
=
repository
;
this
.
includes
=
includes
;
}
/**
* Create a new {@link WebRequestTraceFilter} instance with the default
* {@link Include} to apply.
* @param repository the trace repository
* @see Include#defaultIncludes()
*/
public
WebRequestTraceFilter
(
TraceRepository
repository
)
{
this
(
repository
,
Include
.
defaultIncludes
());
}
/**
* Debugging feature. If enabled, and trace logging is enabled then web request
* headers will be logged.
* @param dumpRequests if requests should be logged
*/
public
void
setDumpRequests
(
boolean
dumpRequests
)
{
this
.
dumpRequests
=
dumpRequests
;
}
@Override
public
int
getOrder
()
{
return
this
.
order
;
}
public
void
setOrder
(
int
order
)
{
this
.
order
=
order
;
}
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
throws
ServletException
,
IOException
{
long
startTime
=
System
.
nanoTime
();
Map
<
String
,
Object
>
trace
=
getTrace
(
request
);
logTrace
(
request
,
trace
);
int
status
=
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
();
try
{
filterChain
.
doFilter
(
request
,
response
);
status
=
response
.
getStatus
();
}
finally
{
addTimeTaken
(
trace
,
startTime
);
enhanceTrace
(
trace
,
status
==
response
.
getStatus
()
?
response
:
new
CustomStatusResponseWrapper
(
response
,
status
));
this
.
repository
.
add
(
trace
);
}
}
protected
Map
<
String
,
Object
>
getTrace
(
HttpServletRequest
request
)
{
HttpSession
session
=
request
.
getSession
(
false
);
Throwable
exception
=
(
Throwable
)
request
.
getAttribute
(
"javax.servlet.error.exception"
);
Principal
userPrincipal
=
request
.
getUserPrincipal
();
Map
<
String
,
Object
>
trace
=
new
LinkedHashMap
<>();
Map
<
String
,
Object
>
headers
=
new
LinkedHashMap
<>();
trace
.
put
(
"method"
,
request
.
getMethod
());
trace
.
put
(
"path"
,
request
.
getRequestURI
());
trace
.
put
(
"headers"
,
headers
);
if
(
isIncluded
(
Include
.
REQUEST_HEADERS
))
{
headers
.
put
(
"request"
,
getRequestHeaders
(
request
));
}
add
(
trace
,
Include
.
PATH_INFO
,
"pathInfo"
,
request
.
getPathInfo
());
add
(
trace
,
Include
.
PATH_TRANSLATED
,
"pathTranslated"
,
request
.
getPathTranslated
());
add
(
trace
,
Include
.
CONTEXT_PATH
,
"contextPath"
,
request
.
getContextPath
());
add
(
trace
,
Include
.
USER_PRINCIPAL
,
"userPrincipal"
,
(
userPrincipal
==
null
?
null
:
userPrincipal
.
getName
()));
if
(
isIncluded
(
Include
.
PARAMETERS
))
{
trace
.
put
(
"parameters"
,
getParameterMapCopy
(
request
));
}
add
(
trace
,
Include
.
QUERY_STRING
,
"query"
,
request
.
getQueryString
());
add
(
trace
,
Include
.
AUTH_TYPE
,
"authType"
,
request
.
getAuthType
());
add
(
trace
,
Include
.
REMOTE_ADDRESS
,
"remoteAddress"
,
request
.
getRemoteAddr
());
add
(
trace
,
Include
.
SESSION_ID
,
"sessionId"
,
(
session
==
null
?
null
:
session
.
getId
()));
add
(
trace
,
Include
.
REMOTE_USER
,
"remoteUser"
,
request
.
getRemoteUser
());
if
(
isIncluded
(
Include
.
ERRORS
)
&&
exception
!=
null
&&
this
.
errorAttributes
!=
null
)
{
trace
.
put
(
"error"
,
this
.
errorAttributes
.
getErrorAttributes
(
new
ServletWebRequest
(
request
),
true
));
}
return
trace
;
}
private
Map
<
String
,
Object
>
getRequestHeaders
(
HttpServletRequest
request
)
{
Map
<
String
,
Object
>
headers
=
new
LinkedHashMap
<>();
Set
<
String
>
excludedHeaders
=
getExcludeHeaders
();
Enumeration
<
String
>
names
=
request
.
getHeaderNames
();
while
(
names
.
hasMoreElements
())
{
String
name
=
names
.
nextElement
();
if
(!
excludedHeaders
.
contains
(
name
.
toLowerCase
()))
{
headers
.
put
(
name
,
getHeaderValue
(
request
,
name
));
}
}
postProcessRequestHeaders
(
headers
);
return
headers
;
}
private
Set
<
String
>
getExcludeHeaders
()
{
Set
<
String
>
excludedHeaders
=
new
HashSet
<>();
if
(!
isIncluded
(
Include
.
COOKIES
))
{
excludedHeaders
.
add
(
"cookie"
);
}
if
(!
isIncluded
(
Include
.
AUTHORIZATION_HEADER
))
{
excludedHeaders
.
add
(
"authorization"
);
}
return
excludedHeaders
;
}
private
Object
getHeaderValue
(
HttpServletRequest
request
,
String
name
)
{
List
<
String
>
value
=
Collections
.
list
(
request
.
getHeaders
(
name
));
if
(
value
.
size
()
==
1
)
{
return
value
.
get
(
0
);
}
if
(
value
.
isEmpty
())
{
return
""
;
}
return
value
;
}
private
Map
<
String
,
String
[]>
getParameterMapCopy
(
HttpServletRequest
request
)
{
return
new
LinkedHashMap
<>(
request
.
getParameterMap
());
}
/**
* Post process request headers before they are added to the trace.
* @param headers a mutable map containing the request headers to trace
* @since 1.4.0
*/
protected
void
postProcessRequestHeaders
(
Map
<
String
,
Object
>
headers
)
{
}
private
void
addTimeTaken
(
Map
<
String
,
Object
>
trace
,
long
startTime
)
{
long
timeTaken
=
System
.
nanoTime
()
-
startTime
;
add
(
trace
,
Include
.
TIME_TAKEN
,
"timeTaken"
,
String
.
valueOf
(
TimeUnit
.
NANOSECONDS
.
toMillis
(
timeTaken
)));
}
@SuppressWarnings
(
"unchecked"
)
protected
void
enhanceTrace
(
Map
<
String
,
Object
>
trace
,
HttpServletResponse
response
)
{
if
(
isIncluded
(
Include
.
RESPONSE_HEADERS
))
{
Map
<
String
,
Object
>
headers
=
(
Map
<
String
,
Object
>)
trace
.
get
(
"headers"
);
headers
.
put
(
"response"
,
getResponseHeaders
(
response
));
}
}
private
Map
<
String
,
String
>
getResponseHeaders
(
HttpServletResponse
response
)
{
Map
<
String
,
String
>
headers
=
new
LinkedHashMap
<>();
for
(
String
header
:
response
.
getHeaderNames
())
{
String
value
=
response
.
getHeader
(
header
);
headers
.
put
(
header
,
value
);
}
if
(!
isIncluded
(
Include
.
COOKIES
))
{
headers
.
remove
(
"Set-Cookie"
);
}
headers
.
put
(
"status"
,
String
.
valueOf
(
response
.
getStatus
()));
return
headers
;
}
private
void
logTrace
(
HttpServletRequest
request
,
Map
<
String
,
Object
>
trace
)
{
if
(
logger
.
isTraceEnabled
())
{
logger
.
trace
(
"Processing request "
+
request
.
getMethod
()
+
" "
+
request
.
getRequestURI
());
if
(
this
.
dumpRequests
)
{
logger
.
trace
(
"Headers: "
+
trace
.
get
(
"headers"
));
}
}
}
private
void
add
(
Map
<
String
,
Object
>
trace
,
Include
include
,
String
name
,
Object
value
)
{
if
(
isIncluded
(
include
)
&&
value
!=
null
)
{
trace
.
put
(
name
,
value
);
}
}
private
boolean
isIncluded
(
Include
include
)
{
return
this
.
includes
.
contains
(
include
);
}
public
void
setErrorAttributes
(
ErrorAttributes
errorAttributes
)
{
this
.
errorAttributes
=
errorAttributes
;
}
private
static
final
class
CustomStatusResponseWrapper
extends
HttpServletResponseWrapper
{
private
final
int
status
;
private
CustomStatusResponseWrapper
(
HttpServletResponse
response
,
int
status
)
{
super
(
response
);
this
.
status
=
status
;
}
@Override
public
int
getStatus
()
{
return
this
.
status
;
}
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/HttpExchangeTracer.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.net.URI
;
import
java.security.Principal
;
import
java.util.Iterator
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.function.Consumer
;
import
java.util.function.Predicate
;
import
java.util.function.Supplier
;
import
org.springframework.http.HttpHeaders
;
/**
* Traces an HTTP request-response exchange.
*
* @author Andy Wilkinson
* @since 2.0.0
*/
public
class
HttpExchangeTracer
{
private
final
Set
<
Include
>
includes
;
/**
* Creates a new {@code HttpExchangeTracer} that will use the given {@code includes}
* to determine the contents of its traces.
* @param includes the includes
*/
public
HttpExchangeTracer
(
Set
<
Include
>
includes
)
{
this
.
includes
=
includes
;
}
/**
* Begins the tracing of the exchange that was initiated by the given {@code request}
* being received.
* @param request the received request
* @return the HTTP trace for the
*/
public
final
HttpTrace
receivedRequest
(
TraceableRequest
request
)
{
return
new
HttpTrace
(
new
FilteredTraceableRequest
(
request
));
}
/**
* Ends the tracing of the exchange that is being concluded by sending the given
* {@code response}.
* @param trace the trace for the exchange
* @param response the response the concludes the exchange
* @param principal a supplier for the exchange's principal
* @param sessionId a supplier for the id of the exchange's session
*/
public
final
void
sendingResponse
(
HttpTrace
trace
,
TraceableResponse
response
,
Supplier
<
Principal
>
principal
,
Supplier
<
String
>
sessionId
)
{
setIfIncluded
(
Include
.
TIME_TAKEN
,
()
->
System
.
currentTimeMillis
()
-
trace
.
getTimestamp
().
toEpochMilli
(),
trace:
:
setTimeTaken
);
setIfIncluded
(
Include
.
SESSION_ID
,
sessionId
,
trace:
:
setSessionId
);
setIfIncluded
(
Include
.
PRINCIPAL
,
principal
,
trace:
:
setPrincipal
);
trace
.
setResponse
(
new
HttpTrace
.
Response
(
new
FilteredTraceableResponse
(
response
)));
}
/**
* Post-process the given mutable map of request {@code headers}.
* @param headers the headers to post-process
*/
protected
void
postProcessRequestHeaders
(
Map
<
String
,
List
<
String
>>
headers
)
{
}
private
<
T
>
T
getIfIncluded
(
Include
include
,
Supplier
<
T
>
valueSupplier
)
{
return
this
.
includes
.
contains
(
include
)
?
valueSupplier
.
get
()
:
null
;
}
private
<
T
>
void
setIfIncluded
(
Include
include
,
Supplier
<
T
>
supplier
,
Consumer
<
T
>
consumer
)
{
if
(
this
.
includes
.
contains
(
include
))
{
consumer
.
accept
(
supplier
.
get
());
}
}
private
Map
<
String
,
List
<
String
>>
getHeadersIfIncluded
(
Include
include
,
Supplier
<
Map
<
String
,
List
<
String
>>>
headersSupplier
,
Predicate
<
String
>
headerPredicate
)
{
if
(!
this
.
includes
.
contains
(
include
))
{
return
new
LinkedHashMap
<>();
}
Map
<
String
,
List
<
String
>>
headers
=
headersSupplier
.
get
();
Iterator
<
String
>
keys
=
headers
.
keySet
().
iterator
();
while
(
keys
.
hasNext
())
{
if
(!
headerPredicate
.
test
(
keys
.
next
()))
{
keys
.
remove
();
}
}
return
headers
;
}
private
final
class
FilteredTraceableRequest
implements
TraceableRequest
{
private
final
TraceableRequest
delegate
;
private
FilteredTraceableRequest
(
TraceableRequest
delegate
)
{
this
.
delegate
=
delegate
;
}
@Override
public
String
getMethod
()
{
return
this
.
delegate
.
getMethod
();
}
@Override
public
URI
getUri
()
{
return
this
.
delegate
.
getUri
();
}
@Override
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
getHeadersIfIncluded
(
Include
.
REQUEST_HEADERS
,
this
.
delegate
::
getHeaders
,
(
name
)
->
{
if
(
name
.
equalsIgnoreCase
(
HttpHeaders
.
COOKIE
))
{
return
HttpExchangeTracer
.
this
.
includes
.
contains
(
Include
.
COOKIE_HEADERS
);
}
if
(
name
.
equalsIgnoreCase
(
HttpHeaders
.
AUTHORIZATION
))
{
return
HttpExchangeTracer
.
this
.
includes
.
contains
(
Include
.
AUTHORIZATION_HEADER
);
}
return
true
;
});
}
@Override
public
String
getRemoteAddress
()
{
return
getIfIncluded
(
Include
.
REMOTE_ADDRESS
,
this
.
delegate
::
getRemoteAddress
);
}
}
private
final
class
FilteredTraceableResponse
implements
TraceableResponse
{
private
final
TraceableResponse
delegate
;
private
FilteredTraceableResponse
(
TraceableResponse
delegate
)
{
this
.
delegate
=
delegate
;
}
@Override
public
int
getStatus
()
{
return
this
.
delegate
.
getStatus
();
}
@Override
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
getHeadersIfIncluded
(
Include
.
RESPONSE_HEADERS
,
this
.
delegate
::
getHeaders
,
(
name
)
->
{
if
(
name
.
equalsIgnoreCase
(
HttpHeaders
.
SET_COOKIE
))
{
return
HttpExchangeTracer
.
this
.
includes
.
contains
(
Include
.
COOKIE_HEADERS
);
}
return
true
;
});
}
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/HttpTrace.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.net.URI
;
import
java.time.Instant
;
import
java.util.List
;
import
java.util.Map
;
import
org.springframework.util.StringUtils
;
/**
* A trace event for handling of an HTTP request and response exchange. Can be used for
* analyzing contextual information such as HTTP headers.
*
* @author Dave Syer
* @author Andy Wilkinson
* @since 2.0.0
*/
public
final
class
HttpTrace
{
private
final
Instant
timestamp
=
Instant
.
now
();
private
volatile
Principal
principal
;
private
volatile
Session
session
;
private
final
Request
request
;
private
volatile
Response
response
;
private
volatile
Long
timeTaken
;
HttpTrace
(
TraceableRequest
request
)
{
this
.
request
=
new
Request
(
request
);
}
public
Instant
getTimestamp
()
{
return
this
.
timestamp
;
}
void
setPrincipal
(
java
.
security
.
Principal
principal
)
{
if
(
principal
!=
null
)
{
this
.
principal
=
new
Principal
(
principal
.
getName
());
}
}
public
Principal
getPrincipal
()
{
return
this
.
principal
;
}
public
Session
getSession
()
{
return
this
.
session
;
}
void
setSessionId
(
String
sessionId
)
{
if
(
StringUtils
.
hasText
(
sessionId
))
{
this
.
session
=
new
Session
(
sessionId
);
}
}
public
Request
getRequest
()
{
return
this
.
request
;
}
public
Response
getResponse
()
{
return
this
.
response
;
}
void
setResponse
(
Response
response
)
{
this
.
response
=
response
;
}
public
Long
getTimeTaken
()
{
return
this
.
timeTaken
;
}
void
setTimeTaken
(
long
timeTaken
)
{
this
.
timeTaken
=
timeTaken
;
}
/**
* Trace of an HTTP request.
*/
public
static
final
class
Request
{
private
final
String
method
;
private
final
URI
uri
;
private
final
Map
<
String
,
List
<
String
>>
headers
;
private
final
String
remoteAddress
;
private
Request
(
TraceableRequest
request
)
{
this
.
method
=
request
.
getMethod
();
this
.
uri
=
request
.
getUri
();
this
.
headers
=
request
.
getHeaders
();
this
.
remoteAddress
=
request
.
getRemoteAddress
();
}
public
String
getMethod
()
{
return
this
.
method
;
}
public
URI
getUri
()
{
return
this
.
uri
;
}
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
this
.
headers
;
}
public
String
getRemoteAddress
()
{
return
this
.
remoteAddress
;
}
}
/**
* Trace of an HTTP response.
*/
public
static
final
class
Response
{
private
final
int
status
;
private
final
Map
<
String
,
List
<
String
>>
headers
;
Response
(
TraceableResponse
response
)
{
this
.
status
=
response
.
getStatus
();
this
.
headers
=
response
.
getHeaders
();
}
public
int
getStatus
()
{
return
this
.
status
;
}
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
this
.
headers
;
}
}
/**
* Session associated with an HTTP request-response exchange.
*/
public
static
final
class
Session
{
private
final
String
id
;
private
Session
(
String
id
)
{
this
.
id
=
id
;
}
public
String
getId
()
{
return
this
.
id
;
}
}
/**
* Principal associated with an HTTP request-response exchange.
*/
public
static
final
class
Principal
{
private
final
String
name
;
private
Principal
(
String
name
)
{
this
.
name
=
name
;
}
public
String
getName
()
{
return
this
.
name
;
}
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
trace/
TraceEndpoint.java
→
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
web/trace/Http
TraceEndpoint.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,7 +14,7 @@
...
@@ -14,7 +14,7 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.util.List
;
import
java.util.List
;
...
@@ -23,21 +23,21 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
...
@@ -23,21 +23,21 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
/**
/**
* {@link Endpoint} to expose {@link Trace} information.
* {@link Endpoint} to expose {@link
Http
Trace} information.
*
*
* @author Dave Syer
* @author Dave Syer
* @since 2.0.0
* @since 2.0.0
*/
*/
@Endpoint
(
id
=
"trace"
)
@Endpoint
(
id
=
"trace"
)
public
class
TraceEndpoint
{
public
class
Http
TraceEndpoint
{
private
final
TraceRepository
repository
;
private
final
Http
TraceRepository
repository
;
/**
/**
* Create a new {@link TraceEndpoint} instance.
* Create a new {@link
Http
TraceEndpoint} instance.
* @param repository the trace repository
* @param repository the trace repository
*/
*/
public
TraceEndpoint
(
TraceRepository
repository
)
{
public
HttpTraceEndpoint
(
Http
TraceRepository
repository
)
{
Assert
.
notNull
(
repository
,
"Repository must not be null"
);
Assert
.
notNull
(
repository
,
"Repository must not be null"
);
this
.
repository
=
repository
;
this
.
repository
=
repository
;
}
}
...
@@ -48,18 +48,18 @@ public class TraceEndpoint {
...
@@ -48,18 +48,18 @@ public class TraceEndpoint {
}
}
/**
/**
* A description of an application's {@link Trace} entries. Primarily intended for
* A description of an application's {@link
Http
Trace} entries. Primarily intended for
* serialization to JSON.
* serialization to JSON.
*/
*/
public
static
final
class
TraceDescriptor
{
public
static
final
class
TraceDescriptor
{
private
final
List
<
Trace
>
traces
;
private
final
List
<
Http
Trace
>
traces
;
private
TraceDescriptor
(
List
<
Trace
>
traces
)
{
private
TraceDescriptor
(
List
<
Http
Trace
>
traces
)
{
this
.
traces
=
traces
;
this
.
traces
=
traces
;
}
}
public
List
<
Trace
>
getTraces
()
{
public
List
<
Http
Trace
>
getTraces
()
{
return
this
.
traces
;
return
this
.
traces
;
}
}
...
...
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
trace/
TraceRepository.java
→
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
web/trace/Http
TraceRepository.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,28 +14,29 @@
...
@@ -14,28 +14,29 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
/**
/**
* A repository for {@link Trace}s.
* A repository for {@link
Http
Trace}s.
*
*
* @author Dave Syer
* @author Dave Syer
* @author Andy Wilkinson
* @since 2.0.0
*/
*/
public
interface
TraceRepository
{
public
interface
Http
TraceRepository
{
/**
/**
* Find all {@link Trace} objects contained in the repository.
* Find all {@link
Http
Trace} objects contained in the repository.
* @return the results
* @return the results
*/
*/
List
<
Trace
>
findAll
();
List
<
Http
Trace
>
findAll
();
/**
/**
* Add
a new {@link Trace} object at the current time
.
* Add
s a trace to the repository
.
* @param trace
Info trace information
* @param trace
the trace to add
*/
*/
void
add
(
Map
<
String
,
Object
>
traceInfo
);
void
add
(
HttpTrace
trace
);
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
trace/InMemory
TraceRepository.java
→
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
web/trace/InMemoryHttp
TraceRepository.java
View file @
3565961d
...
@@ -14,28 +14,27 @@
...
@@ -14,28 +14,27 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.time.Instant
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.LinkedList
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
/**
/**
* In-memory implementation of {@link TraceRepository}.
* In-memory implementation of {@link
Http
TraceRepository}.
*
*
* @author Dave Syer
* @author Dave Syer
* @author Olivier Bourgain
* @author Olivier Bourgain
* @since 2.0.0
*/
*/
public
class
InMemory
TraceRepository
implements
TraceRepository
{
public
class
InMemory
HttpTraceRepository
implements
Http
TraceRepository
{
private
int
capacity
=
100
;
private
int
capacity
=
100
;
private
boolean
reverse
=
true
;
private
boolean
reverse
=
true
;
private
final
List
<
Trace
>
traces
=
new
LinkedList
<>();
private
final
List
<
Http
Trace
>
traces
=
new
LinkedList
<>();
/**
/**
* Flag to say that the repository lists traces in reverse order.
* Flag to say that the repository lists traces in reverse order.
...
@@ -58,15 +57,14 @@ public class InMemoryTraceRepository implements TraceRepository {
...
@@ -58,15 +57,14 @@ public class InMemoryTraceRepository implements TraceRepository {
}
}
@Override
@Override
public
List
<
Trace
>
findAll
()
{
public
List
<
Http
Trace
>
findAll
()
{
synchronized
(
this
.
traces
)
{
synchronized
(
this
.
traces
)
{
return
Collections
.
unmodifiableList
(
new
ArrayList
<>(
this
.
traces
));
return
Collections
.
unmodifiableList
(
new
ArrayList
<>(
this
.
traces
));
}
}
}
}
@Override
@Override
public
void
add
(
Map
<
String
,
Object
>
map
)
{
public
void
add
(
HttpTrace
trace
)
{
Trace
trace
=
new
Trace
(
Instant
.
now
(),
map
);
synchronized
(
this
.
traces
)
{
synchronized
(
this
.
traces
)
{
while
(
this
.
traces
.
size
()
>=
this
.
capacity
)
{
while
(
this
.
traces
.
size
()
>=
this
.
capacity
)
{
this
.
traces
.
remove
(
this
.
reverse
?
this
.
capacity
-
1
:
0
);
this
.
traces
.
remove
(
this
.
reverse
?
this
.
capacity
-
1
:
0
);
...
...
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/trace/Include.java
→
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
web/
trace/Include.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,14 +14,14 @@
...
@@ -14,14 +14,14 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedHashSet
;
import
java.util.Set
;
import
java.util.Set
;
/**
/**
* Include options for tracing.
* Include options for
HTTP
tracing.
*
*
* @author Wallace Wadge
* @author Wallace Wadge
* @since 2.0.0
* @since 2.0.0
...
@@ -39,9 +39,10 @@ public enum Include {
...
@@ -39,9 +39,10 @@ public enum Include {
RESPONSE_HEADERS
,
RESPONSE_HEADERS
,
/**
/**
* Include "Cookie" in request and "Set-Cookie" in response headers.
* Include "Cookie" header (if any) in request headers and "Set-Cookie" (if any) in
* response headers.
*/
*/
COOKIES
,
COOKIE
_HEADER
S
,
/**
/**
* Include authorization header (if any).
* Include authorization header (if any).
...
@@ -49,44 +50,9 @@ public enum Include {
...
@@ -49,44 +50,9 @@ public enum Include {
AUTHORIZATION_HEADER
,
AUTHORIZATION_HEADER
,
/**
/**
* Include
errors (if any)
.
* Include
the principal
.
*/
*/
ERRORS
,
PRINCIPAL
,
/**
* Include path info.
*/
PATH_INFO
,
/**
* Include the translated path.
*/
PATH_TRANSLATED
,
/**
* Include the context path.
*/
CONTEXT_PATH
,
/**
* Include the user principal.
*/
USER_PRINCIPAL
,
/**
* Include the parameters.
*/
PARAMETERS
,
/**
* Include the query string.
*/
QUERY_STRING
,
/**
* Include the authentication type.
*/
AUTH_TYPE
,
/**
/**
* Include the remote address.
* Include the remote address.
...
@@ -98,11 +64,6 @@ public enum Include {
...
@@ -98,11 +64,6 @@ public enum Include {
*/
*/
SESSION_ID
,
SESSION_ID
,
/**
* Include the remote user.
*/
REMOTE_USER
,
/**
/**
* Include the time taken to service the request in milliseconds.
* Include the time taken to service the request in milliseconds.
*/
*/
...
@@ -114,8 +75,7 @@ public enum Include {
...
@@ -114,8 +75,7 @@ public enum Include {
Set
<
Include
>
defaultIncludes
=
new
LinkedHashSet
<>();
Set
<
Include
>
defaultIncludes
=
new
LinkedHashSet
<>();
defaultIncludes
.
add
(
Include
.
REQUEST_HEADERS
);
defaultIncludes
.
add
(
Include
.
REQUEST_HEADERS
);
defaultIncludes
.
add
(
Include
.
RESPONSE_HEADERS
);
defaultIncludes
.
add
(
Include
.
RESPONSE_HEADERS
);
defaultIncludes
.
add
(
Include
.
COOKIES
);
defaultIncludes
.
add
(
Include
.
COOKIE_HEADERS
);
defaultIncludes
.
add
(
Include
.
ERRORS
);
defaultIncludes
.
add
(
Include
.
TIME_TAKEN
);
defaultIncludes
.
add
(
Include
.
TIME_TAKEN
);
DEFAULT_INCLUDES
=
Collections
.
unmodifiableSet
(
defaultIncludes
);
DEFAULT_INCLUDES
=
Collections
.
unmodifiableSet
(
defaultIncludes
);
}
}
...
...
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
trace/Trace
.java
→
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
web/trace/TraceableRequest
.java
View file @
3565961d
...
@@ -14,38 +14,43 @@
...
@@ -14,38 +14,43 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.time.Instant
;
import
java.net.URI
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
org.springframework.util.Assert
;
/**
/**
* A value object representing a trace event: at a particular time with a simple (map)
* A representation of an HTTP request that is suitable for tracing.
* information. Can be used for analyzing contextual information such as HTTP headers.
*
*
* @author Dave Syer
* @author Andy Wilkinson
* @since 2.0.0
* @see HttpExchangeTracer
*/
*/
public
final
class
Trace
{
public
interface
TraceableRequest
{
private
final
Instant
timestamp
;
/**
* Returns the method (GET, POST, etc) of the request.
private
final
Map
<
String
,
Object
>
info
;
* @return the method
*/
public
Trace
(
Instant
timestamp
,
Map
<
String
,
Object
>
info
)
{
String
getMethod
();
Assert
.
notNull
(
timestamp
,
"Timestamp must not be null"
);
Assert
.
notNull
(
info
,
"Info must not be null"
);
/**
this
.
timestamp
=
timestamp
;
* Returns the URI of the request.
this
.
info
=
info
;
* @return the URI
}
*/
URI
getUri
();
public
Instant
getTimestamp
()
{
return
this
.
timestamp
;
/**
}
* Returns a modifiable copy of the headers of the request.
* @return the headers
public
Map
<
String
,
Object
>
getInfo
()
{
*/
return
this
.
info
;
Map
<
String
,
List
<
String
>>
getHeaders
();
}
/**
* Returns the remote address from which the request was sent, if available.
* @return the remote address or {@code null}
*/
String
getRemoteAddress
();
}
}
spring-boot-project/spring-boot-actuator/src/
test/java/org/springframework/boot/actuate/trace/TraceEndpointTests
.java
→
spring-boot-project/spring-boot-actuator/src/
main/java/org/springframework/boot/actuate/web/trace/TraceableResponse
.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,28 +14,30 @@
...
@@ -14,28 +14,30 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
org.junit.Test
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
/**
*
Tests for {@link TraceEndpoint}
.
*
A representation of an HTTP response that is suitable for tracing
.
*
*
* @author Phillip Webb
* @author Andy Wilkinson
* @author Andy Wilkinson
* @since 2.0.0
* @see HttpExchangeTracer
*/
*/
public
class
TraceEndpointTests
{
public
interface
TraceableResponse
{
/**
* The status of the response.
* @return the status
*/
int
getStatus
();
@Test
/**
public
void
trace
()
{
* Returns a modifiable copy of the headers of the response.
TraceRepository
repository
=
new
InMemoryTraceRepository
();
* @return the headers
repository
.
add
(
Collections
.
singletonMap
(
"a"
,
"b"
));
*/
Trace
trace
=
new
TraceEndpoint
(
repository
).
traces
().
getTraces
().
get
(
0
);
Map
<
String
,
List
<
String
>>
getHeaders
();
assertThat
(
trace
.
getInfo
().
get
(
"a"
)).
isEqualTo
(
"b"
);
}
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/trace/package-info.java
→
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/
web/
trace/package-info.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -15,8 +15,8 @@
...
@@ -15,8 +15,8 @@
*/
*/
/**
/**
* Actuator tracing support.
* Actuator
HTTP
tracing support.
*
*
* @see org.springframework.boot.actuate.
trace.
TraceRepository
* @see org.springframework.boot.actuate.
web.trace.Http
TraceRepository
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/reactive/HttpTraceWebFilter.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
reactive
;
import
java.security.Principal
;
import
java.util.Set
;
import
reactor.core.publisher.Mono
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
org.springframework.boot.actuate.web.trace.HttpTrace
;
import
org.springframework.boot.actuate.web.trace.HttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.Include
;
import
org.springframework.core.Ordered
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.server.reactive.ServerHttpResponse
;
import
org.springframework.http.server.reactive.ServerHttpResponseDecorator
;
import
org.springframework.web.server.ResponseStatusException
;
import
org.springframework.web.server.ServerWebExchange
;
import
org.springframework.web.server.WebFilter
;
import
org.springframework.web.server.WebFilterChain
;
import
org.springframework.web.server.WebSession
;
/**
* A {@link WebFilter} for tracing HTTP requests.
*
* @author Andy Wilkinson
* @since 2.0.0
*/
public
class
HttpTraceWebFilter
implements
WebFilter
,
Ordered
{
private
static
final
Object
NONE
=
new
Object
();
// Not LOWEST_PRECEDENCE, but near the end, so it has a good chance of catching all
// enriched headers, but users can add stuff after this if they want to
private
int
order
=
Ordered
.
LOWEST_PRECEDENCE
-
10
;
private
final
HttpTraceRepository
repository
;
private
final
HttpExchangeTracer
tracer
;
private
final
Set
<
Include
>
includes
;
public
HttpTraceWebFilter
(
HttpTraceRepository
repository
,
HttpExchangeTracer
tracer
,
Set
<
Include
>
includes
)
{
this
.
repository
=
repository
;
this
.
tracer
=
tracer
;
this
.
includes
=
includes
;
}
@Override
public
int
getOrder
()
{
return
this
.
order
;
}
public
void
setOrder
(
int
order
)
{
this
.
order
=
order
;
}
@Override
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
,
WebFilterChain
chain
)
{
Mono
<?>
principal
=
this
.
includes
.
contains
(
Include
.
PRINCIPAL
)
?
exchange
.
getPrincipal
().
cast
(
Object
.
class
).
defaultIfEmpty
(
NONE
)
:
Mono
.
just
(
NONE
);
Mono
<?>
session
=
this
.
includes
.
contains
(
Include
.
SESSION_ID
)
?
exchange
.
getSession
()
:
Mono
.
just
(
NONE
);
return
Mono
.
zip
(
principal
,
session
)
.
flatMap
((
tuple
)
->
filter
(
exchange
,
chain
,
asType
(
tuple
.
getT1
(),
Principal
.
class
),
asType
(
tuple
.
getT2
(),
WebSession
.
class
)));
}
private
<
T
>
T
asType
(
Object
object
,
Class
<
T
>
type
)
{
if
(
type
.
isInstance
(
object
))
{
return
type
.
cast
(
object
);
}
return
null
;
}
private
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
,
WebFilterChain
chain
,
Principal
principal
,
WebSession
session
)
{
ServerWebExchangeTraceableRequest
request
=
new
ServerWebExchangeTraceableRequest
(
exchange
);
HttpTrace
trace
=
this
.
tracer
.
receivedRequest
(
request
);
return
chain
.
filter
(
exchange
).
doAfterSuccessOrError
((
aVoid
,
ex
)
->
{
this
.
tracer
.
sendingResponse
(
trace
,
new
TraceableServerHttpResponse
(
ex
==
null
?
exchange
.
getResponse
()
:
new
CustomStatusResponseDecorator
(
ex
,
exchange
.
getResponse
())),
()
->
principal
,
()
->
getStartedSessionId
(
session
));
this
.
repository
.
add
(
trace
);
});
}
private
String
getStartedSessionId
(
WebSession
session
)
{
return
(
session
!=
null
&&
session
.
isStarted
())
?
session
.
getId
()
:
null
;
}
private
static
final
class
CustomStatusResponseDecorator
extends
ServerHttpResponseDecorator
{
private
final
HttpStatus
status
;
private
CustomStatusResponseDecorator
(
Throwable
ex
,
ServerHttpResponse
delegate
)
{
super
(
delegate
);
this
.
status
=
ex
instanceof
ResponseStatusException
?
((
ResponseStatusException
)
ex
).
getStatus
()
:
HttpStatus
.
INTERNAL_SERVER_ERROR
;
}
@Override
public
HttpStatus
getStatusCode
()
{
return
this
.
status
;
}
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/reactive/ServerWebExchangeTraceableRequest.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
reactive
;
import
java.net.URI
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.springframework.boot.actuate.web.trace.TraceableRequest
;
import
org.springframework.http.server.reactive.ServerHttpRequest
;
import
org.springframework.web.server.ServerWebExchange
;
/**
* A {@link TraceableRequest} backed by a {@link ServerWebExchange}.
*
* @author Andy Wilkinson
*/
class
ServerWebExchangeTraceableRequest
implements
TraceableRequest
{
private
final
String
method
;
private
final
Map
<
String
,
List
<
String
>>
headers
;
private
final
URI
uri
;
private
final
String
remoteAddress
;
ServerWebExchangeTraceableRequest
(
ServerWebExchange
exchange
)
{
ServerHttpRequest
request
=
exchange
.
getRequest
();
this
.
method
=
request
.
getMethodValue
();
this
.
headers
=
request
.
getHeaders
();
this
.
uri
=
request
.
getURI
();
this
.
remoteAddress
=
request
.
getRemoteAddress
()
==
null
?
null
:
request
.
getRemoteAddress
().
getAddress
().
toString
();
}
@Override
public
String
getMethod
()
{
return
this
.
method
;
}
@Override
public
URI
getUri
()
{
return
this
.
uri
;
}
@Override
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
new
LinkedHashMap
<>(
this
.
headers
);
}
@Override
public
String
getRemoteAddress
()
{
return
this
.
remoteAddress
;
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/reactive/TraceableServerHttpResponse.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
reactive
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
org.springframework.boot.actuate.web.trace.TraceableResponse
;
import
org.springframework.http.server.reactive.ServerHttpResponse
;
/**
* An adapter that exposes a {@link ServerHttpResponse} as a {@link TraceableResponse}.
*
* @author Andy Wilkinson
*/
class
TraceableServerHttpResponse
implements
TraceableResponse
{
private
final
ServerHttpResponse
response
;
TraceableServerHttpResponse
(
ServerHttpResponse
exchange
)
{
this
.
response
=
exchange
;
}
@Override
public
int
getStatus
()
{
return
this
.
response
.
getStatusCode
()
==
null
?
200
:
this
.
response
.
getStatusCode
().
value
();
}
@Override
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
new
LinkedHashMap
<>(
this
.
response
.
getHeaders
());
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/reactive/package-info.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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.
*/
/**
* Actuator reactive HTTP tracing support.
*
* @see org.springframework.boot.actuate.web.trace.HttpTraceRepository
*/
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
.
reactive
;
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/servlet/HttpTraceFilter.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
servlet
;
import
java.io.IOException
;
import
javax.servlet.Filter
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponseWrapper
;
import
javax.servlet.http.HttpSession
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
org.springframework.boot.actuate.web.trace.HttpTrace
;
import
org.springframework.boot.actuate.web.trace.HttpTraceRepository
;
import
org.springframework.core.Ordered
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.filter.OncePerRequestFilter
;
/**
* Servlet {@link Filter} that logs all requests to an {@link HttpTraceRepository}.
*
* @author Dave Syer
* @author Wallace Wadge
* @author Andy Wilkinson
* @author Venil Noronha
* @author Madhura Bhave
* @since 2.0.0
*/
public
class
HttpTraceFilter
extends
OncePerRequestFilter
implements
Ordered
{
// Not LOWEST_PRECEDENCE, but near the end, so it has a good chance of catching all
// enriched headers, but users can add stuff after this if they want to
private
int
order
=
Ordered
.
LOWEST_PRECEDENCE
-
10
;
private
final
HttpTraceRepository
repository
;
private
final
HttpExchangeTracer
tracer
;
/**
* Create a new {@link HttpTraceFilter} instance.
* @param repository the trace repository
* @param tracer used to trace exchanges
*/
public
HttpTraceFilter
(
HttpTraceRepository
repository
,
HttpExchangeTracer
tracer
)
{
this
.
repository
=
repository
;
this
.
tracer
=
tracer
;
}
@Override
public
int
getOrder
()
{
return
this
.
order
;
}
public
void
setOrder
(
int
order
)
{
this
.
order
=
order
;
}
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
throws
ServletException
,
IOException
{
TraceableHttpServletRequest
traceableRequest
=
new
TraceableHttpServletRequest
(
request
);
HttpTrace
trace
=
this
.
tracer
.
receivedRequest
(
traceableRequest
);
int
status
=
HttpStatus
.
INTERNAL_SERVER_ERROR
.
value
();
try
{
filterChain
.
doFilter
(
request
,
response
);
status
=
response
.
getStatus
();
}
finally
{
TraceableHttpServletResponse
traceableResponse
=
new
TraceableHttpServletResponse
(
status
==
response
.
getStatus
()
?
response
:
new
CustomStatusResponseWrapper
(
response
,
status
));
this
.
tracer
.
sendingResponse
(
trace
,
traceableResponse
,
request:
:
getUserPrincipal
,
()
->
getSessionId
(
request
));
this
.
repository
.
add
(
trace
);
}
}
private
String
getSessionId
(
HttpServletRequest
request
)
{
HttpSession
session
=
request
.
getSession
(
false
);
return
session
==
null
?
null
:
session
.
getId
();
}
private
static
final
class
CustomStatusResponseWrapper
extends
HttpServletResponseWrapper
{
private
final
int
status
;
private
CustomStatusResponseWrapper
(
HttpServletResponse
response
,
int
status
)
{
super
(
response
);
this
.
status
=
status
;
}
@Override
public
int
getStatus
()
{
return
this
.
status
;
}
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/servlet/TraceableHttpServletRequest.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
servlet
;
import
java.net.URI
;
import
java.util.ArrayList
;
import
java.util.Enumeration
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
javax.servlet.http.HttpServletRequest
;
import
org.springframework.boot.actuate.web.trace.TraceableRequest
;
import
org.springframework.util.StringUtils
;
/**
* An adapter that exposes an {@link HttpServletRequest} as a {@link TraceableRequest}.
*
* @author Andy Wilkinson
*/
final
class
TraceableHttpServletRequest
implements
TraceableRequest
{
private
final
HttpServletRequest
request
;
TraceableHttpServletRequest
(
HttpServletRequest
request
)
{
this
.
request
=
request
;
}
@Override
public
String
getMethod
()
{
return
this
.
request
.
getMethod
();
}
@Override
public
URI
getUri
()
{
StringBuffer
urlBuffer
=
this
.
request
.
getRequestURL
();
if
(
StringUtils
.
hasText
(
this
.
request
.
getQueryString
()))
{
urlBuffer
.
append
(
"?"
);
urlBuffer
.
append
(
this
.
request
.
getQueryString
());
}
return
URI
.
create
(
urlBuffer
.
toString
());
}
@Override
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
extractHeaders
();
}
@Override
public
String
getRemoteAddress
()
{
return
this
.
request
.
getRemoteAddr
();
}
private
Map
<
String
,
List
<
String
>>
extractHeaders
()
{
Map
<
String
,
List
<
String
>>
headers
=
new
LinkedHashMap
<>();
Enumeration
<
String
>
names
=
this
.
request
.
getHeaderNames
();
while
(
names
.
hasMoreElements
())
{
String
name
=
names
.
nextElement
();
headers
.
put
(
name
,
toList
(
this
.
request
.
getHeaders
(
name
)));
}
return
headers
;
}
private
List
<
String
>
toList
(
Enumeration
<
String
>
enumeration
)
{
List
<
String
>
list
=
new
ArrayList
<
String
>();
while
(
enumeration
.
hasMoreElements
())
{
list
.
add
(
enumeration
.
nextElement
());
}
return
list
;
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/servlet/TraceableHttpServletResponse.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
servlet
;
import
java.util.ArrayList
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
javax.servlet.http.HttpServletResponse
;
import
org.springframework.boot.actuate.web.trace.TraceableResponse
;
/**
* An adapter that exposes an {@link HttpServletResponse} as a {@link TraceableResponse}.
*
* @author Andy Wilkinson
*/
final
class
TraceableHttpServletResponse
implements
TraceableResponse
{
private
final
HttpServletResponse
delegate
;
TraceableHttpServletResponse
(
HttpServletResponse
response
)
{
this
.
delegate
=
response
;
}
@Override
public
int
getStatus
()
{
return
this
.
delegate
.
getStatus
();
}
@Override
public
Map
<
String
,
List
<
String
>>
getHeaders
()
{
return
extractHeaders
();
}
private
Map
<
String
,
List
<
String
>>
extractHeaders
()
{
Map
<
String
,
List
<
String
>>
headers
=
new
LinkedHashMap
<>();
for
(
String
name
:
this
.
delegate
.
getHeaderNames
())
{
headers
.
put
(
name
,
new
ArrayList
<>(
this
.
delegate
.
getHeaders
(
name
)));
}
return
headers
;
}
}
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/trace/servlet/package-info.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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.
*/
/**
* Actuator servlet HTTP tracing support.
*
* @see org.springframework.boot.actuate.web.trace.HttpTraceRepository
*/
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
.
servlet
;
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/trace/WebRequestTraceFilterTests.java
deleted
100644 → 0
View file @
11064b5d
This diff is collapsed.
Click to expand it.
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/trace/HttpExchangeTracerTests.java
0 → 100644
View file @
3565961d
This diff is collapsed.
Click to expand it.
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/trace/InMemoryTraceRepositoryTests.java
→
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/
web/
trace/InMemoryTraceRepositoryTests.java
View file @
3565961d
/*
/*
* Copyright 2012-201
7
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -14,47 +14,55 @@
...
@@ -14,47 +14,55 @@
* limitations under the License.
* limitations under the License.
*/
*/
package
org
.
springframework
.
boot
.
actuate
.
trace
;
package
org
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
org.junit.Test
;
import
org.junit.Test
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
/**
* Tests for {@link InMemoryTraceRepository}.
* Tests for {@link InMemory
Http
TraceRepository}.
*
*
* @author Dave Syer
* @author Dave Syer
* @author Andy Wilkinson
*/
*/
public
class
InMemoryTraceRepositoryTests
{
public
class
InMemoryTraceRepositoryTests
{
private
final
InMemory
TraceRepository
repository
=
new
InMemory
TraceRepository
();
private
final
InMemory
HttpTraceRepository
repository
=
new
InMemoryHttp
TraceRepository
();
@Test
@Test
public
void
capacityLimited
()
{
public
void
capacityLimited
()
{
this
.
repository
.
setCapacity
(
2
);
this
.
repository
.
setCapacity
(
2
);
this
.
repository
.
add
(
Collections
.
singletonMap
(
"foo"
,
"bar"
));
this
.
repository
.
add
(
new
HttpTrace
(
createRequest
(
"GET"
)
));
this
.
repository
.
add
(
Collections
.
singletonMap
(
"bar"
,
"foo"
));
this
.
repository
.
add
(
new
HttpTrace
(
createRequest
(
"POST"
)
));
this
.
repository
.
add
(
Collections
.
singletonMap
(
"bar"
,
"bar"
));
this
.
repository
.
add
(
new
HttpTrace
(
createRequest
(
"DELETE"
)
));
List
<
Trace
>
traces
=
this
.
repository
.
findAll
();
List
<
Http
Trace
>
traces
=
this
.
repository
.
findAll
();
assertThat
(
traces
).
hasSize
(
2
);
assertThat
(
traces
).
hasSize
(
2
);
assertThat
(
traces
.
get
(
0
).
get
Info
().
get
(
"bar"
)).
isEqualTo
(
"bar
"
);
assertThat
(
traces
.
get
(
0
).
get
Request
().
getMethod
()).
isEqualTo
(
"DELETE
"
);
assertThat
(
traces
.
get
(
1
).
get
Info
().
get
(
"bar"
)).
isEqualTo
(
"foo
"
);
assertThat
(
traces
.
get
(
1
).
get
Request
().
getMethod
()).
isEqualTo
(
"POST
"
);
}
}
@Test
@Test
public
void
reverseFalse
()
{
public
void
reverseFalse
()
{
this
.
repository
.
setReverse
(
false
);
this
.
repository
.
setReverse
(
false
);
this
.
repository
.
setCapacity
(
2
);
this
.
repository
.
setCapacity
(
2
);
this
.
repository
.
add
(
Collections
.
singletonMap
(
"foo"
,
"bar"
));
this
.
repository
.
add
(
new
HttpTrace
(
createRequest
(
"GET"
)
));
this
.
repository
.
add
(
Collections
.
singletonMap
(
"bar"
,
"foo"
));
this
.
repository
.
add
(
new
HttpTrace
(
createRequest
(
"POST"
)
));
this
.
repository
.
add
(
Collections
.
singletonMap
(
"bar"
,
"bar"
));
this
.
repository
.
add
(
new
HttpTrace
(
createRequest
(
"DELETE"
)
));
List
<
Trace
>
traces
=
this
.
repository
.
findAll
();
List
<
Http
Trace
>
traces
=
this
.
repository
.
findAll
();
assertThat
(
traces
).
hasSize
(
2
);
assertThat
(
traces
).
hasSize
(
2
);
assertThat
(
traces
.
get
(
1
).
getInfo
().
get
(
"bar"
)).
isEqualTo
(
"bar"
);
assertThat
(
traces
.
get
(
0
).
getRequest
().
getMethod
()).
isEqualTo
(
"POST"
);
assertThat
(
traces
.
get
(
0
).
getInfo
().
get
(
"bar"
)).
isEqualTo
(
"foo"
);
assertThat
(
traces
.
get
(
1
).
getRequest
().
getMethod
()).
isEqualTo
(
"DELETE"
);
}
private
TraceableRequest
createRequest
(
String
method
)
{
TraceableRequest
request
=
mock
(
TraceableRequest
.
class
);
given
(
request
.
getMethod
()).
willReturn
(
method
);
return
request
;
}
}
}
}
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/trace/TraceEndpointTests.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
;
import
java.util.List
;
import
org.junit.Test
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
* Tests for {@link HttpTraceEndpoint}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
public
class
TraceEndpointTests
{
@Test
public
void
trace
()
{
HttpTraceRepository
repository
=
new
InMemoryHttpTraceRepository
();
repository
.
add
(
new
HttpTrace
(
createRequest
(
"GET"
)));
List
<
HttpTrace
>
traces
=
new
HttpTraceEndpoint
(
repository
).
traces
().
getTraces
();
assertThat
(
traces
).
hasSize
(
1
);
HttpTrace
trace
=
traces
.
get
(
0
);
assertThat
(
trace
.
getRequest
().
getMethod
()).
isEqualTo
(
"GET"
);
}
private
TraceableRequest
createRequest
(
String
method
)
{
TraceableRequest
request
=
mock
(
TraceableRequest
.
class
);
given
(
request
.
getMethod
()).
willReturn
(
method
);
return
request
;
}
}
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/trace/reactive/HttpTraceWebFilterIntegrationTests.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
reactive
;
import
java.util.EnumSet
;
import
java.util.Set
;
import
org.junit.Test
;
import
reactor.core.publisher.Mono
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
org.springframework.boot.actuate.web.trace.HttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.InMemoryHttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.Include
;
import
org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.server.reactive.HttpHandler
;
import
org.springframework.test.web.reactive.server.WebTestClient
;
import
org.springframework.web.reactive.config.EnableWebFlux
;
import
org.springframework.web.reactive.function.server.HandlerFunction
;
import
org.springframework.web.reactive.function.server.RequestPredicates
;
import
org.springframework.web.reactive.function.server.RouterFunction
;
import
org.springframework.web.reactive.function.server.RouterFunctions
;
import
org.springframework.web.reactive.function.server.ServerResponse
;
import
org.springframework.web.server.adapter.WebHttpHandlerBuilder
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Integration tests for {@link HttpTraceWebFilter}.
*
* @author Andy Wilkinson
*/
public
class
HttpTraceWebFilterIntegrationTests
{
@Test
public
void
traceForNotFoundResponseHas404Status
()
{
ReactiveWebApplicationContextRunner
runner
=
new
ReactiveWebApplicationContextRunner
()
.
withUserConfiguration
(
Config
.
class
);
runner
.
run
((
context
)
->
{
WebTestClient
.
bindToApplicationContext
(
context
).
build
().
get
().
uri
(
"/"
)
.
exchange
().
expectStatus
().
isNotFound
();
HttpTraceRepository
repository
=
context
.
getBean
(
HttpTraceRepository
.
class
);
assertThat
(
repository
.
findAll
()).
hasSize
(
1
);
assertThat
(
repository
.
findAll
().
get
(
0
).
getResponse
().
getStatus
())
.
isEqualTo
(
404
);
});
}
@Test
public
void
traceForMonoErrorWithRuntimeExceptionHas500Status
()
{
ReactiveWebApplicationContextRunner
runner
=
new
ReactiveWebApplicationContextRunner
()
.
withUserConfiguration
(
Config
.
class
);
runner
.
run
((
context
)
->
{
WebTestClient
.
bindToApplicationContext
(
context
).
build
().
get
()
.
uri
(
"/mono-error"
).
exchange
().
expectStatus
()
.
isEqualTo
(
HttpStatus
.
INTERNAL_SERVER_ERROR
);
HttpTraceRepository
repository
=
context
.
getBean
(
HttpTraceRepository
.
class
);
assertThat
(
repository
.
findAll
()).
hasSize
(
1
);
assertThat
(
repository
.
findAll
().
get
(
0
).
getResponse
().
getStatus
())
.
isEqualTo
(
500
);
});
}
@Test
public
void
traceForThrownRuntimeExceptionHas500Status
()
{
ReactiveWebApplicationContextRunner
runner
=
new
ReactiveWebApplicationContextRunner
()
.
withUserConfiguration
(
Config
.
class
);
runner
.
run
((
context
)
->
{
WebTestClient
.
bindToApplicationContext
(
context
).
build
().
get
().
uri
(
"/thrown"
)
.
exchange
().
expectStatus
()
.
isEqualTo
(
HttpStatus
.
INTERNAL_SERVER_ERROR
);
HttpTraceRepository
repository
=
context
.
getBean
(
HttpTraceRepository
.
class
);
assertThat
(
repository
.
findAll
()).
hasSize
(
1
);
assertThat
(
repository
.
findAll
().
get
(
0
).
getResponse
().
getStatus
())
.
isEqualTo
(
500
);
});
}
@Configuration
@EnableWebFlux
static
class
Config
{
@Bean
public
HttpTraceWebFilter
httpTraceWebFilter
(
HttpTraceRepository
repository
)
{
Set
<
Include
>
includes
=
EnumSet
.
allOf
(
Include
.
class
);
return
new
HttpTraceWebFilter
(
repository
,
new
HttpExchangeTracer
(
includes
),
includes
);
}
@Bean
public
HttpTraceRepository
httpTraceRepository
()
{
return
new
InMemoryHttpTraceRepository
();
}
@Bean
public
HttpHandler
httpHandler
(
ApplicationContext
applicationContext
)
{
return
WebHttpHandlerBuilder
.
applicationContext
(
applicationContext
).
build
();
}
@Bean
public
RouterFunction
<
ServerResponse
>
router
()
{
return
RouterFunctions
.
route
(
RequestPredicates
.
GET
(
"/mono-error"
),
(
request
)
->
Mono
.
error
(
new
RuntimeException
()))
.
andRoute
(
RequestPredicates
.
GET
(
"/thrown"
),
(
HandlerFunction
<
ServerResponse
>)
(
request
)
->
{
throw
new
RuntimeException
();
});
}
}
}
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/trace/reactive/HttpTraceWebFilterTests.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
reactive
;
import
java.io.IOException
;
import
java.security.Principal
;
import
java.util.EnumSet
;
import
javax.servlet.ServletException
;
import
org.junit.Test
;
import
reactor.core.publisher.Mono
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
org.springframework.boot.actuate.web.trace.HttpTrace.Session
;
import
org.springframework.boot.actuate.web.trace.InMemoryHttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.Include
;
import
org.springframework.mock.http.server.reactive.MockServerHttpRequest
;
import
org.springframework.mock.web.server.MockServerWebExchange
;
import
org.springframework.web.server.ServerWebExchange
;
import
org.springframework.web.server.ServerWebExchangeDecorator
;
import
org.springframework.web.server.WebFilterChain
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
* Tests for {@link HttpTraceWebFilter}.
*
* @author Andy Wilkinson
*/
public
class
HttpTraceWebFilterTests
{
private
final
InMemoryHttpTraceRepository
repository
=
new
InMemoryHttpTraceRepository
();
private
final
HttpExchangeTracer
tracer
=
new
HttpExchangeTracer
(
EnumSet
.
allOf
(
Include
.
class
));
private
final
HttpTraceWebFilter
filter
=
new
HttpTraceWebFilter
(
this
.
repository
,
this
.
tracer
,
EnumSet
.
allOf
(
Include
.
class
));
@Test
public
void
filterTracesExchange
()
throws
ServletException
,
IOException
{
this
.
filter
.
filter
(
MockServerWebExchange
.
from
(
MockServerHttpRequest
.
get
(
"https://api.example.com"
)),
new
WebFilterChain
()
{
@Override
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
)
{
return
Mono
.
empty
();
}
}).
block
();
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
}
@Test
public
void
filterCapturesSessionIdWhenSessionIsUsed
()
throws
ServletException
,
IOException
{
this
.
filter
.
filter
(
MockServerWebExchange
.
from
(
MockServerHttpRequest
.
get
(
"https://api.example.com"
)),
new
WebFilterChain
()
{
@Override
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
)
{
exchange
.
getSession
().
block
().
getAttributes
().
put
(
"a"
,
"alpha"
);
return
Mono
.
empty
();
}
}).
block
();
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
Session
session
=
this
.
repository
.
findAll
().
get
(
0
).
getSession
();
assertThat
(
session
).
isNotNull
();
assertThat
(
session
.
getId
()).
isNotNull
();
}
@Test
public
void
filterDoesNotCaptureIdOfUnusedSession
()
throws
ServletException
,
IOException
{
this
.
filter
.
filter
(
MockServerWebExchange
.
from
(
MockServerHttpRequest
.
get
(
"https://api.example.com"
)),
new
WebFilterChain
()
{
@Override
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
)
{
exchange
.
getSession
().
block
();
return
Mono
.
empty
();
}
}).
block
();
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
Session
session
=
this
.
repository
.
findAll
().
get
(
0
).
getSession
();
assertThat
(
session
).
isNull
();
}
@Test
public
void
filterCapturesPrincipal
()
throws
ServletException
,
IOException
{
Principal
principal
=
mock
(
Principal
.
class
);
given
(
principal
.
getName
()).
willReturn
(
"alice"
);
this
.
filter
.
filter
(
new
ServerWebExchangeDecorator
(
MockServerWebExchange
.
from
(
MockServerHttpRequest
.
get
(
"https://api.example.com"
)))
{
@Override
public
Mono
<
Principal
>
getPrincipal
()
{
return
Mono
.
just
(
principal
);
}
},
new
WebFilterChain
()
{
@Override
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
)
{
exchange
.
getSession
().
block
().
getAttributes
().
put
(
"a"
,
"alpha"
);
return
Mono
.
empty
();
}
}).
block
();
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
org
.
springframework
.
boot
.
actuate
.
web
.
trace
.
HttpTrace
.
Principal
tracedPrincipal
=
this
.
repository
.
findAll
().
get
(
0
).
getPrincipal
();
assertThat
(
tracedPrincipal
).
isNotNull
();
assertThat
(
tracedPrincipal
.
getName
()).
isEqualTo
(
"alice"
);
}
@Test
public
void
statusIsAssumedToBe500WhenChainFails
()
throws
ServletException
,
IOException
{
try
{
this
.
filter
.
filter
(
MockServerWebExchange
.
from
(
MockServerHttpRequest
.
get
(
"https://api.example.com"
)),
new
WebFilterChain
()
{
@Override
public
Mono
<
Void
>
filter
(
ServerWebExchange
exchange
)
{
return
Mono
.
error
(
new
RuntimeException
());
}
}).
block
();
fail
();
}
catch
(
Exception
ex
)
{
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
assertThat
(
this
.
repository
.
findAll
().
get
(
0
).
getResponse
().
getStatus
())
.
isEqualTo
(
500
);
}
}
}
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/web/trace/servlet/HttpTraceFilterTests.java
0 → 100644
View file @
3565961d
/*
* Copyright 2012-2018 the original author or authors.
*
* 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
.
springframework
.
boot
.
actuate
.
web
.
trace
.
servlet
;
import
java.io.IOException
;
import
java.security.Principal
;
import
java.util.EnumSet
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.junit.Test
;
import
org.springframework.boot.actuate.web.trace.HttpExchangeTracer
;
import
org.springframework.boot.actuate.web.trace.HttpTrace.Session
;
import
org.springframework.boot.actuate.web.trace.InMemoryHttpTraceRepository
;
import
org.springframework.boot.actuate.web.trace.Include
;
import
org.springframework.mock.web.MockFilterChain
;
import
org.springframework.mock.web.MockHttpServletRequest
;
import
org.springframework.mock.web.MockHttpServletResponse
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
Mockito
.
mock
;
/**
* Tests for {@link HttpTraceFilter}.
*
* @author Dave Syer
* @author Wallace Wadge
* @author Phillip Webb
* @author Andy Wilkinson
* @author Venil Noronha
* @author Stephane Nicoll
* @author Madhura Bhave
*/
public
class
HttpTraceFilterTests
{
private
final
InMemoryHttpTraceRepository
repository
=
new
InMemoryHttpTraceRepository
();
private
final
HttpExchangeTracer
tracer
=
new
HttpExchangeTracer
(
EnumSet
.
allOf
(
Include
.
class
));
private
final
HttpTraceFilter
filter
=
new
HttpTraceFilter
(
this
.
repository
,
this
.
tracer
);
@Test
public
void
filterTracesExchange
()
throws
ServletException
,
IOException
{
this
.
filter
.
doFilter
(
new
MockHttpServletRequest
(),
new
MockHttpServletResponse
(),
new
MockFilterChain
());
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
}
@Test
public
void
filterCapturesSessionId
()
throws
ServletException
,
IOException
{
this
.
filter
.
doFilter
(
new
MockHttpServletRequest
(),
new
MockHttpServletResponse
(),
new
MockFilterChain
(
new
HttpServlet
()
{
@Override
protected
void
service
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
req
.
getSession
(
true
);
}
}));
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
Session
session
=
this
.
repository
.
findAll
().
get
(
0
).
getSession
();
assertThat
(
session
).
isNotNull
();
assertThat
(
session
.
getId
()).
isNotNull
();
}
@Test
public
void
filterCapturesPrincipal
()
throws
ServletException
,
IOException
{
MockHttpServletRequest
request
=
new
MockHttpServletRequest
();
Principal
principal
=
mock
(
Principal
.
class
);
given
(
principal
.
getName
()).
willReturn
(
"alice"
);
request
.
setUserPrincipal
(
principal
);
this
.
filter
.
doFilter
(
request
,
new
MockHttpServletResponse
(),
new
MockFilterChain
());
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
org
.
springframework
.
boot
.
actuate
.
web
.
trace
.
HttpTrace
.
Principal
tracedPrincipal
=
this
.
repository
.
findAll
().
get
(
0
).
getPrincipal
();
assertThat
(
tracedPrincipal
).
isNotNull
();
assertThat
(
tracedPrincipal
.
getName
()).
isEqualTo
(
"alice"
);
}
@Test
public
void
statusIsAssumedToBe500WhenChainFails
()
throws
ServletException
,
IOException
{
try
{
this
.
filter
.
doFilter
(
new
MockHttpServletRequest
(),
new
MockHttpServletResponse
(),
new
MockFilterChain
(
new
HttpServlet
()
{
@Override
protected
void
service
(
HttpServletRequest
req
,
HttpServletResponse
resp
)
throws
ServletException
,
IOException
{
throw
new
IOException
();
}
}));
fail
(
"Filter swallowed IOException"
);
}
catch
(
IOException
ex
)
{
assertThat
(
this
.
repository
.
findAll
()).
hasSize
(
1
);
assertThat
(
this
.
repository
.
findAll
().
get
(
0
).
getResponse
().
getStatus
())
.
isEqualTo
(
500
);
}
}
}
spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
View file @
3565961d
...
@@ -115,7 +115,7 @@ store. Not available when using Spring Session's support for reactive web applic
...
@@ -115,7 +115,7 @@ store. Not available when using Spring Session's support for reactive web applic
|Performs a thread dump.
|Performs a thread dump.
|`trace`
|`trace`
|Displays trace information (by default, the last 100 HTTP requests).
|Displays
HTTP
trace information (by default, the last 100 HTTP requests).
|===
|===
If your application is a web application (Spring MVC, Spring WebFlux, or Jersey), you can
If your application is a web application (Spring MVC, Spring WebFlux, or Jersey), you can
...
@@ -1161,71 +1161,14 @@ implementing `ApplicationEventPublisherAware`).
...
@@ -1161,71 +1161,14 @@ implementing `ApplicationEventPublisherAware`).
[[production-ready-tracing]]
[[production-ready-tracing]]
== Tracing
== Tracing
Tracing is automatically enabled for all HTTP requests. You can view the `trace` endpoint
Tracing is automatically enabled for all HTTP requests. You can view the `trace` endpoint
and obtain basic information about the last 100 requests. The following listing shows
and obtain basic information about the last 100 requests.
sample output:
[source,json,indent=0]
----
[{
"timestamp": 1394343677415,
"info": {
"method": "GET",
"path": "/trace",
"headers": {
"request": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Connection": "keep-alive",
"Accept-Encoding": "gzip, deflate",
"User-Agent": "Mozilla/5.0 Gecko/Firefox",
"Accept-Language": "en-US,en;q=0.5",
"Cookie": "_ga=GA1.1.827067509.1390890128; ..."
"Authorization": "Basic ...",
"Host": "localhost:8080"
},
"response": {
"Strict-Transport-Security": "max-age=31536000 ; includeSubDomains",
"X-Application-Context": "application:8080",
"Content-Type": "application/json;charset=UTF-8",
"status": "200"
}
}
}
},{
"timestamp": 1394343684465,
...
}]
----
By default, the trace includes the following information:
[cols="1,2"]
|===
|Name |Description
|Request Headers
|Headers from the request.
|Response Headers
|Headers from the response.
|Cookies
|`Cookie` from request headers and `Set-Cookie` from response headers.
|Errors
|The error attributes (if any).
|Time Taken
|The time taken to service the request in milliseconds.
|===
[[production-ready-custom-tracing]]
[[production-ready-custom-tracing]]
=== Custom tracing
=== Custom tracing
If you need to trace additional events, you can inject a
To customize the items that are included in each trace, use the
{sc-spring-boot-actuator}/trace/TraceRepository.{sc-ext}[`TraceRepository`] into your
`management.trace.include` configuration property.
Spring beans. The `add` method accepts a single `Map` structure that is converted to JSON
and logged.
By default, an `InMemoryTraceRepository` that stores the last 100 events is used. If you
By default, an `InMemoryTraceRepository` that stores the last 100 events is used. If you
need to expand the capacity, you can define your own instance of the
need to expand the capacity, you can define your own instance of the
...
...
spring-boot-project/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc
View file @
3565961d
...
@@ -2660,6 +2660,9 @@ does so, the orders shown in the following table will be used:
...
@@ -2660,6 +2660,9 @@ does so, the orders shown in the following table will be used:
|`WebFilterChainProxy` (Spring Security)
|`WebFilterChainProxy` (Spring Security)
|`-100`
|`-100`
|`HttpTraceWebFilter`
|`Ordered.LOWEST_PRECEDENCE - 10`
|===
|===
...
@@ -2794,7 +2797,7 @@ precedence):
...
@@ -2794,7 +2797,7 @@ precedence):
|`ErrorPageFilter`
|`ErrorPageFilter`
|`Ordered.HIGHEST_PRECEDENCE + 1`
|`Ordered.HIGHEST_PRECEDENCE + 1`
|`
WebRequest
TraceFilter`
|`
Http
TraceFilter`
|`Ordered.LOWEST_PRECEDENCE - 10`
|`Ordered.LOWEST_PRECEDENCE - 10`
|===
|===
...
...
spring-boot-samples/spring-boot-sample-actuator/src/main/resources/application.properties
View file @
3565961d
...
@@ -18,6 +18,4 @@ spring.jmx.enabled=true
...
@@ -18,6 +18,4 @@ spring.jmx.enabled=true
spring.jackson.serialization.write_dates_as_timestamps
=
false
spring.jackson.serialization.write_dates_as_timestamps
=
false
management.trace.include
=
REQUEST_HEADERS,RESPONSE_HEADERS,ERRORS,PATH_INFO,
\
management.trace.include
=
REQUEST_HEADERS,RESPONSE_HEADERS,PRINCIPAL,REMOTE_ADDRESS,SESSION_ID
PATH_TRANSLATED,CONTEXT_PATH,USER_PRINCIPAL,PARAMETERS,QUERY_STRING,AUTH_TYPE,
\
REMOTE_ADDRESS,SESSION_ID,REMOTE_USER
spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/SampleActuatorApplicationTests.java
View file @
3565961d
...
@@ -166,41 +166,6 @@ public class SampleActuatorApplicationTests {
...
@@ -166,41 +166,6 @@ public class SampleActuatorApplicationTests {
assertThat
(
body
).
contains
(
"This application has no explicit mapping for /error"
);
assertThat
(
body
).
contains
(
"This application has no explicit mapping for /error"
);
}
}
@Test
@SuppressWarnings
(
"unchecked"
)
public
void
testTrace
()
{
this
.
restTemplate
.
getForEntity
(
"/health"
,
String
.
class
);
@SuppressWarnings
(
"rawtypes"
)
ResponseEntity
<
Map
>
entity
=
this
.
restTemplate
.
withBasicAuth
(
"user"
,
getPassword
())
.
getForEntity
(
"/actuator/trace"
,
Map
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
Map
<
String
,
Object
>
body
=
entity
.
getBody
();
Map
<
String
,
Object
>
trace
=
((
List
<
Map
<
String
,
Object
>>)
body
.
get
(
"traces"
))
.
get
(
0
);
Map
<
String
,
Object
>
map
=
(
Map
<
String
,
Object
>)
((
Map
<
String
,
Object
>)
((
Map
<
String
,
Object
>)
trace
.
get
(
"info"
)).
get
(
"headers"
)).
get
(
"response"
);
assertThat
(
map
.
get
(
"status"
)).
isEqualTo
(
"200"
);
}
@Test
@SuppressWarnings
(
"unchecked"
)
public
void
traceWithParameterMap
()
{
this
.
restTemplate
.
withBasicAuth
(
"user"
,
getPassword
())
.
getForEntity
(
"/actuator/health?param1=value1"
,
String
.
class
);
@SuppressWarnings
(
"rawtypes"
)
ResponseEntity
<
Map
>
entity
=
this
.
restTemplate
.
withBasicAuth
(
"user"
,
getPassword
())
.
getForEntity
(
"/actuator/trace"
,
Map
.
class
);
assertThat
(
entity
.
getStatusCode
()).
isEqualTo
(
HttpStatus
.
OK
);
Map
<
String
,
Object
>
body
=
entity
.
getBody
();
Map
<
String
,
Object
>
trace
=
((
List
<
Map
<
String
,
Object
>>)
body
.
get
(
"traces"
))
.
get
(
0
);
Map
<
String
,
Object
>
map
=
(
Map
<
String
,
Object
>)
((
Map
<
String
,
Object
>)
trace
.
get
(
"info"
)).
get
(
"parameters"
);
assertThat
(
map
.
get
(
"param1"
)).
isNotNull
();
}
@Test
@Test
public
void
testErrorPageDirectAccess
()
{
public
void
testErrorPageDirectAccess
()
{
@SuppressWarnings
(
"rawtypes"
)
@SuppressWarnings
(
"rawtypes"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment