@@ -21,7 +21,7 @@ import akka.stream.ActorMaterializer
21
21
import kamon .tag .Lookups .{plain , plainBoolean , plainLong }
22
22
import kamon .testkit ._
23
23
import kamon .trace .Span .Mark
24
- import okhttp3 .{OkHttpClient , Request }
24
+ import okhttp3 .{OkHttpClient , Protocol , Request }
25
25
import org .scalatest ._
26
26
import org .scalatest .concurrent .{Eventually , ScalaFutures }
27
27
import org .scalatest .matchers .should .Matchers
@@ -30,6 +30,7 @@ import org.scalatest.wordspec.AnyWordSpecLike
30
30
import java .util .UUID
31
31
import javax .net .ssl .{HostnameVerifier , SSLSession }
32
32
import scala .concurrent .duration ._
33
+ import scala .collection .JavaConverters ._
33
34
34
35
class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with ScalaFutures with Inside with InitAndStopKamonAfterAll
35
36
with MetricInspection .Syntax with Reconfigure with TestWebServer with Eventually with OptionValues with TestSpanReporter {
@@ -46,27 +47,35 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
46
47
.hostnameVerifier(new HostnameVerifier { override def verify (s : String , sslSession : SSLSession ): Boolean = true })
47
48
.build()
48
49
50
+ val okHttp1ONly = new OkHttpClient .Builder ()
51
+ .sslSocketFactory(sslSocketFactory, trustManager)
52
+ .protocols(List (Protocol .HTTP_1_1 ).asJava)
53
+ .hostnameVerifier(new HostnameVerifier { override def verify (s : String , sslSession : SSLSession ): Boolean = true })
54
+ .build()
55
+
49
56
val timeoutTest : FiniteDuration = 5 second
50
57
val interface = " 127.0.0.1"
51
- val http1WebServer = startServer(interface, 8081 , https = false )
52
- val http2WebServer = startServer(interface, 8082 , https = true )
58
+ val httpWebServer = startServer(interface, 8081 , https = false )
59
+ val httpsWebServer = startServer(interface, 8082 , https = true )
53
60
54
- testSuite(" HTTP/1" , http1WebServer)
55
- testSuite(" HTTP/2" , http2WebServer)
61
+ testSuite(" HTTP" , httpWebServer, okHttp)
62
+ testSuite(" HTTPS" , httpsWebServer, okHttp)
63
+ testSuite(" HTTPS with HTTP/1 only clients" , httpsWebServer, okHttp1ONly)
56
64
57
- def testSuite (httpVersion : String , server : WebServer ) = {
65
+ def testSuite (httpVersion : String , server : WebServer , client : OkHttpClient ) = {
58
66
val interface = server.interface
59
67
val port = server.port
60
68
val protocol = server.protocol
61
69
62
70
s " the Akka HTTP server instrumentation with ${httpVersion}" should {
63
71
" create a server Span when receiving requests" in {
64
72
val target = s " $protocol:// $interface: $port/ $dummyPathOk"
65
- okHttp.newCall(new Request .Builder ().url(target).build()).execute()
73
+ client.newCall(new Request .Builder ().url(target).build()).execute()
74
+
66
75
67
76
eventually(timeout(10 seconds)) {
68
77
val span = testSpanReporter().nextSpan().value
69
- span.tags.get(plain(" http.url" )) shouldBe target
78
+ span.tags.get(plain(" http.url" )) should endWith( s " $interface : $port / $dummyPathOk " )
70
79
span.metricTags.get(plain(" component" )) shouldBe " akka.http.server"
71
80
span.metricTags.get(plain(" http.method" )) shouldBe " GET"
72
81
span.metricTags.get(plainLong(" http.status_code" )) shouldBe 200L
@@ -76,7 +85,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
76
85
" return the correct operation name with overloaded route" in {
77
86
val target = s " $protocol:// $interface: $port/some_endpoint "
78
87
79
- okHttp .newCall(new Request .Builder ()
88
+ client .newCall(new Request .Builder ()
80
89
.get()
81
90
.url(target).build())
82
91
.execute()
@@ -89,7 +98,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
89
98
val path = s " extraction/nested/42/fixed/anchor/32/ ${UUID .randomUUID().toString}/fixed/44/CafE "
90
99
val expected = " /extraction/nested/{}/fixed/anchor/{}/{}/fixed/{}/{}"
91
100
val target = s " $protocol:// $interface: $port/ $path"
92
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
101
+ client .newCall(new Request .Builder ().url(target).build()).execute()
93
102
94
103
eventually(timeout(10 seconds)) {
95
104
val span = testSpanReporter().nextSpan().value
@@ -101,7 +110,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
101
110
val path = " extraction/segment/special**"
102
111
val expected = " /extraction/segment/{}"
103
112
val target = s " $protocol:// $interface: $port/ $path"
104
- val response = okHttp .newCall(new Request .Builder ().url(target).build()).execute()
113
+ val response = client .newCall(new Request .Builder ().url(target).build()).execute()
105
114
106
115
response.code() shouldBe 200
107
116
response.body().string() shouldBe " special**"
@@ -116,7 +125,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
116
125
val path = " extraction/on-complete/42/more-path"
117
126
val expected = " /extraction/on-complete/{}/more-path"
118
127
val target = s " $protocol:// $interface: $port/ $path"
119
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
128
+ client .newCall(new Request .Builder ().url(target).build()).execute()
120
129
121
130
eventually(timeout(10 seconds)) {
122
131
val span = testSpanReporter().nextSpan().value
@@ -128,7 +137,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
128
137
val path = " extraction/on-success/42/after"
129
138
val expected = " /extraction/on-success/{}/after"
130
139
val target = s " $protocol:// $interface: $port/ $path"
131
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
140
+ client .newCall(new Request .Builder ().url(target).build()).execute()
132
141
133
142
eventually(timeout(10 seconds)) {
134
143
val span = testSpanReporter().nextSpan().value
@@ -140,7 +149,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
140
149
val path = " extraction/complete-or-recover-with/42/after"
141
150
val expected = " /extraction/complete-or-recover-with/{}/after"
142
151
val target = s " $protocol:// $interface: $port/ $path"
143
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
152
+ client .newCall(new Request .Builder ().url(target).build()).execute()
144
153
145
154
eventually(timeout(10 seconds)) {
146
155
val span = testSpanReporter().nextSpan().value
@@ -152,7 +161,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
152
161
val path = " extraction/complete-or-recover-with-success/42/after"
153
162
val expected = " /extraction/complete-or-recover-with-success/{}"
154
163
val target = s " $protocol:// $interface: $port/ $path"
155
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
164
+ client .newCall(new Request .Builder ().url(target).build()).execute()
156
165
157
166
eventually(timeout(10 seconds)) {
158
167
val span = testSpanReporter().nextSpan().value
@@ -164,7 +173,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
164
173
val path = s " v3/user/3/post/3 "
165
174
val expected = " /v3/user/{}/post/{}"
166
175
val target = s " $protocol:// $interface: $port/ $path"
167
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
176
+ client .newCall(new Request .Builder ().url(target).build()).execute()
168
177
169
178
eventually(timeout(10 seconds)) {
170
179
val span = testSpanReporter().nextSpan().value
@@ -175,12 +184,12 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
175
184
176
185
" change the Span operation name when using the operationName directive" in {
177
186
val target = s " $protocol:// $interface: $port/ $traceOk"
178
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
187
+ client .newCall(new Request .Builder ().url(target).build()).execute()
179
188
180
189
eventually(timeout(10 seconds)) {
181
190
val span = testSpanReporter().nextSpan().value
182
191
span.operationName shouldBe " user-supplied-operation"
183
- span.tags.get(plain(" http.url" )) shouldBe target
192
+ span.tags.get(plain(" http.url" )) should endWith( s " $interface : $port / $traceOk " )
184
193
span.metricTags.get(plain(" component" )) shouldBe " akka.http.server"
185
194
span.metricTags.get(plain(" http.method" )) shouldBe " GET"
186
195
span.metricTags.get(plainLong(" http.status_code" )) shouldBe 200L
@@ -189,12 +198,12 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
189
198
190
199
" mark spans as failed when request fails" in {
191
200
val target = s " $protocol:// $interface: $port/ $dummyPathError"
192
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
201
+ client .newCall(new Request .Builder ().url(target).build()).execute()
193
202
194
203
eventually(timeout(10 seconds)) {
195
204
val span = testSpanReporter().nextSpan().value
196
205
span.operationName shouldBe s " / $dummyPathError"
197
- span.tags.get(plain(" http.url" )) shouldBe target
206
+ span.tags.get(plain(" http.url" )) should endWith( s " $interface : $port / $dummyPathError " )
198
207
span.metricTags.get(plain(" component" )) shouldBe " akka.http.server"
199
208
span.metricTags.get(plain(" http.method" )) shouldBe " GET"
200
209
span.metricTags.get(plainBoolean(" error" )) shouldBe true
@@ -204,12 +213,12 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
204
213
205
214
" change the operation name to 'unhandled' when the response status code is 404" in {
206
215
val target = s " $protocol:// $interface: $port/unknown-path "
207
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
216
+ client .newCall(new Request .Builder ().url(target).build()).execute()
208
217
209
218
eventually(timeout(10 seconds)) {
210
219
val span = testSpanReporter().nextSpan().value
211
220
span.operationName shouldBe " unhandled"
212
- span.tags.get(plain(" http.url" )) shouldBe target
221
+ span.tags.get(plain(" http.url" )) should endWith( s " $interface : $port /unknown-path " )
213
222
span.metricTags.get(plain(" component" )) shouldBe " akka.http.server"
214
223
span.metricTags.get(plain(" http.method" )) shouldBe " GET"
215
224
span.metricTags.get(plainBoolean(" error" )) shouldBe false
@@ -219,7 +228,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
219
228
220
229
" correctly time entity transfer timings" in {
221
230
val target = s " $protocol:// $interface: $port/ $stream"
222
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
231
+ client .newCall(new Request .Builder ().url(target).build()).execute()
223
232
224
233
val span = eventually(timeout(10 seconds)) {
225
234
val span = testSpanReporter().nextSpan().value
@@ -231,14 +240,14 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
231
240
case List (_ @ Mark (_, " http.response.ready" )) =>
232
241
}
233
242
234
- span.tags.get(plain(" http.url" )) shouldBe target
243
+ span.tags.get(plain(" http.url" )) should endWith( s " $interface : $port / $stream " )
235
244
span.metricTags.get(plain(" component" )) shouldBe " akka.http.server"
236
245
span.metricTags.get(plain(" http.method" )) shouldBe " GET"
237
246
}
238
247
239
248
" include the trace-id and keep all user-provided headers in the responses" in {
240
249
val target = s " $protocol:// $interface: $port/extra-header "
241
- val response = okHttp .newCall(new Request .Builder ().url(target).build()).execute()
250
+ val response = client .newCall(new Request .Builder ().url(target).build()).execute()
242
251
243
252
response.headers().names() should contain allOf (
244
253
" trace-id" ,
@@ -248,7 +257,7 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
248
257
249
258
" keep operation names provided by the HTTP Server instrumentation" in {
250
259
val target = s " $protocol:// $interface: $port/name-will-be-changed "
251
- okHttp .newCall(new Request .Builder ().url(target).build()).execute()
260
+ client .newCall(new Request .Builder ().url(target).build()).execute()
252
261
253
262
eventually(timeout(10 seconds)) {
254
263
val span = testSpanReporter().nextSpan().value
@@ -260,8 +269,8 @@ class AkkaHttpServerTracingSpec extends AnyWordSpecLike with Matchers with Scala
260
269
261
270
override protected def afterAll (): Unit = {
262
271
super .afterAll()
263
- http1WebServer .shutdown()
264
- http2WebServer .shutdown()
272
+ httpWebServer .shutdown()
273
+ httpsWebServer .shutdown()
265
274
}
266
275
}
267
276
0 commit comments