@@ -18,11 +18,10 @@ package kamon.spring
1818
1919import com .typesafe .config .ConfigFactory
2020import kamon .Kamon
21+ import kamon .spring .client .HttpClientSupport
2122import kamon .spring .webapp .AppSupport
2223import kamon .trace .Span
2324import kamon .trace .Span .TagValue
24- import org .apache .http .client .methods .{CloseableHttpResponse , HttpGet }
25- import org .apache .http .impl .client .HttpClients
2625import org .scalatest .concurrent .Eventually
2726import org .scalatest .{BeforeAndAfterAll , Matchers , OptionValues , WordSpec }
2827
@@ -34,7 +33,8 @@ class AsyncServerInstrumentationSpec extends WordSpec
3433 with Eventually
3534 with OptionValues
3635 with SpanReporter
37- with AppSupport {
36+ with AppSupport
37+ with HttpClientSupport {
3838
3939 override protected def beforeAll (): Unit = {
4040 Kamon .reconfigure(ConfigFactory .load())
@@ -47,33 +47,21 @@ class AsyncServerInstrumentationSpec extends WordSpec
4747 stopApp()
4848 }
4949
50- private val httpClient = HttpClients .createDefault()
51-
52- private def get (path : String , headers : Seq [(String , String )] = Seq ()): CloseableHttpResponse = {
53- val request = new HttpGet (s " http://127.0.0.1: $port$path" )
54- headers.foreach { case (name, v) => request.addHeader(name, v) }
55- httpClient.execute(request)
56- }
57-
5850 " The Server instrumentation on Spring Boot with Async Servlet" should {
5951 " propagate the current context and respond to the ok action" in {
6052
6153 get(" /async/tracing/ok" ).getStatusLine.getStatusCode shouldBe 200
6254
6355 eventually(timeout(3 seconds)) {
64-
6556 val span = reporter.nextSpan().value
6657 val spanTags = stringTag(span) _
6758
6859 span.operationName shouldBe " async.tracing.ok.get"
6960 spanTags(" span.kind" ) shouldBe " server"
70- spanTags(" component" ) shouldBe " servlet. server"
61+ spanTags(" component" ) shouldBe " spring- server"
7162 spanTags(" http.method" ) shouldBe " GET"
7263 spanTags(" http.url" ) shouldBe " /async/tracing/ok"
7364 span.tags(" http.status_code" ) shouldBe TagValue .Number (200 )
74-
75- // span.from.until(span.to, ChronoUnit.MILLIS) shouldBe >= (servlet.durationOk.toLong)
76-
7765 }
7866 }
7967
@@ -87,12 +75,10 @@ class AsyncServerInstrumentationSpec extends WordSpec
8775
8876 span.operationName shouldBe " not-found"
8977 spanTags(" span.kind" ) shouldBe " server"
90- spanTags(" component" ) shouldBe " servlet. server"
78+ spanTags(" component" ) shouldBe " spring- server"
9179 spanTags(" http.method" ) shouldBe " GET"
9280 spanTags(" http.url" ) shouldBe " /async/tracing/not-found"
9381 span.tags(" http.status_code" ) shouldBe TagValue .Number (404 )
94-
95- // span.from.until(span.to, ChronoUnit.MILLIS) shouldBe >= (servlet.durationNotFound.toLong)
9682 }
9783 }
9884
@@ -105,37 +91,72 @@ class AsyncServerInstrumentationSpec extends WordSpec
10591
10692 span.operationName shouldBe " async.tracing.error.get"
10793 spanTags(" span.kind" ) shouldBe " server"
108- spanTags(" component" ) shouldBe " servlet. server"
94+ spanTags(" component" ) shouldBe " spring- server"
10995 spanTags(" http.method" ) shouldBe " GET"
11096 spanTags(" http.url" ) shouldBe " /async/tracing/error"
11197 span.tags(" error" ) shouldBe TagValue .True
11298 span.tags(" http.status_code" ) shouldBe TagValue .Number (500 )
113-
114- // span.from.until(span.to, ChronoUnit.MILLIS) shouldBe >= (servlet.durationError.toLong)
11599 }
116100 }
117101
118102 " propagate the current context and respond to the error action produced with an internal exception" in {
119- get(" /async/tracing/unhandled-error " ).getStatusLine.getStatusCode shouldBe 500
103+ get(" /async/tracing/exception " ).getStatusLine.getStatusCode shouldBe 500
120104
121105 eventually(timeout(3 seconds)) {
122106 val span = reporter.nextSpan().value
123107 val spanTags = stringTag(span) _
124108
125- span.operationName shouldBe " async.tracing.unhandled-error .get"
109+ span.operationName shouldBe " async.tracing.exception .get"
126110 spanTags(" span.kind" ) shouldBe " server"
127- spanTags(" component" ) shouldBe " servlet. server"
111+ spanTags(" component" ) shouldBe " spring- server"
128112 spanTags(" http.method" ) shouldBe " GET"
129- spanTags(" http.url" ) shouldBe " /async/tracing/unhandled-error "
113+ spanTags(" http.url" ) shouldBe " /async/tracing/exception "
130114 span.tags(" error" ) shouldBe TagValue .True
131115 span.tags(" http.status_code" ) shouldBe TagValue .Number (500 )
116+ }
117+ }
118+
119+ " resume the incoming context and respond to the ok endpoint" in {
120+ get(" /async/tracing/ok" , IncomingContext .headersB3).getStatusLine.getStatusCode shouldBe 200
121+
122+ eventually(timeout(3 seconds)) {
123+
124+ val span = reporter.nextSpan().value
125+ val spanTags = stringTag(span) _
126+
127+ span.operationName shouldBe " async.tracing.ok.get"
128+ spanTags(" span.kind" ) shouldBe " server"
129+ spanTags(" component" ) shouldBe " spring-server"
130+ spanTags(" http.method" ) shouldBe " GET"
131+ spanTags(" http.url" ) shouldBe " /async/tracing/ok"
132+ span.tags(" http.status_code" ) shouldBe TagValue .Number (200 )
132133
133- // span.from.until(span.to, ChronoUnit.MILLIS) shouldBe >= (servlet.durationError.toLong)
134+ span.context.parentID.string shouldBe IncomingContext .SpanId
135+ span.context.traceID.string shouldBe IncomingContext .TraceId
134136 }
135137 }
136138 }
137139
138140 def stringTag (span : Span .FinishedSpan )(tag : String ): String = {
139141 span.tags(tag).asInstanceOf [TagValue .String ].string
140142 }
143+
144+ private object IncomingContext {
145+ import kamon .trace .SpanCodec .B3 .{Headers => B3Headers }
146+
147+ val TraceId = " 1234"
148+ val ParentSpanId = " 2222"
149+ val SpanId = " 4321"
150+ val Sampled = " 1"
151+ val Flags = " some=baggage;more=baggage;other=baggage2"
152+
153+
154+ val headersB3 = Seq (
155+ (B3Headers .TraceIdentifier , TraceId ),
156+ (B3Headers .ParentSpanIdentifier , ParentSpanId ),
157+ (B3Headers .SpanIdentifier , SpanId ),
158+ (B3Headers .Sampled , Sampled ),
159+ (B3Headers .Flags , Flags ))
160+
161+ }
141162}
0 commit comments