196 lines
4.8 KiB
Scala
196 lines
4.8 KiB
Scala
/*
|
|
* Copyright The OpenTelemetry 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.
|
|
*/
|
|
|
|
import java.util.concurrent.CountDownLatch
|
|
|
|
import io.opentelemetry.OpenTelemetry
|
|
import io.opentelemetry.trace.Tracer
|
|
|
|
import scala.concurrent.ExecutionContext.Implicits.global
|
|
import scala.concurrent.duration._
|
|
import scala.concurrent.{Await, Future, Promise}
|
|
|
|
class ScalaConcurrentTests {
|
|
val TRACER: Tracer =
|
|
OpenTelemetry.getTracerProvider.get("io.opentelemetry.auto")
|
|
|
|
/**
|
|
* @return Number of expected spans in the trace
|
|
*/
|
|
def traceWithFutureAndCallbacks() {
|
|
val parentSpan = TRACER.spanBuilder("parent").startSpan()
|
|
val parentScope = TRACER.withSpan(parentSpan)
|
|
try {
|
|
val latch = new CountDownLatch(2)
|
|
val goodFuture: Future[Integer] = Future {
|
|
tracedChild("goodFuture")
|
|
1
|
|
}
|
|
goodFuture onSuccess {
|
|
case _ => {
|
|
tracedChild("successCallback")
|
|
latch.countDown()
|
|
}
|
|
}
|
|
val badFuture: Future[Integer] = Future {
|
|
tracedChild("badFuture")
|
|
throw new RuntimeException("Uh-oh")
|
|
}
|
|
badFuture onFailure {
|
|
case t: Throwable => {
|
|
tracedChild("failureCallback")
|
|
latch.countDown()
|
|
}
|
|
}
|
|
|
|
latch.await()
|
|
} finally {
|
|
parentSpan.end()
|
|
parentScope.close()
|
|
}
|
|
}
|
|
|
|
def tracedAcrossThreadsWithNoTrace() {
|
|
val parentSpan = TRACER.spanBuilder("parent").startSpan()
|
|
val parentScope = TRACER.withSpan(parentSpan)
|
|
try {
|
|
val latch = new CountDownLatch(1)
|
|
val goodFuture: Future[Integer] = Future {
|
|
1
|
|
}
|
|
goodFuture onSuccess {
|
|
case _ =>
|
|
Future {
|
|
2
|
|
} onSuccess {
|
|
case _ => {
|
|
tracedChild("callback")
|
|
latch.countDown()
|
|
}
|
|
}
|
|
}
|
|
|
|
latch.await()
|
|
} finally {
|
|
parentSpan.end()
|
|
parentScope.close()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return Number of expected spans in the trace
|
|
*/
|
|
def traceWithPromises() {
|
|
val parentSpan = TRACER.spanBuilder("parent").startSpan()
|
|
val parentScope = TRACER.withSpan(parentSpan)
|
|
try {
|
|
val keptPromise = Promise[Boolean]()
|
|
val brokenPromise = Promise[Boolean]()
|
|
val afterPromise = keptPromise.future
|
|
val afterPromise2 = keptPromise.future
|
|
|
|
val failedAfterPromise = brokenPromise.future
|
|
|
|
Future {
|
|
tracedChild("future1")
|
|
keptPromise success true
|
|
brokenPromise failure new IllegalStateException()
|
|
}
|
|
|
|
val latch = new CountDownLatch(3)
|
|
afterPromise onSuccess {
|
|
case b => {
|
|
tracedChild("keptPromise")
|
|
latch.countDown()
|
|
}
|
|
}
|
|
afterPromise2 onSuccess {
|
|
case b => {
|
|
tracedChild("keptPromise2")
|
|
latch.countDown()
|
|
}
|
|
}
|
|
|
|
failedAfterPromise onFailure {
|
|
case t => {
|
|
tracedChild("brokenPromise")
|
|
latch.countDown()
|
|
}
|
|
}
|
|
|
|
latch.await()
|
|
} finally {
|
|
parentSpan.end()
|
|
parentScope.close()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return Number of expected spans in the trace
|
|
*/
|
|
def tracedWithFutureFirstCompletions() {
|
|
val parentSpan = TRACER.spanBuilder("parent").startSpan()
|
|
val parentScope = TRACER.withSpan(parentSpan)
|
|
try {
|
|
val completedVal = Future.firstCompletedOf(List(Future {
|
|
tracedChild("timeout1")
|
|
false
|
|
}, Future {
|
|
tracedChild("timeout2")
|
|
false
|
|
}, Future {
|
|
tracedChild("timeout3")
|
|
true
|
|
}))
|
|
Await.result(completedVal, 30 seconds)
|
|
} finally {
|
|
parentSpan.end()
|
|
parentScope.close()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return Number of expected spans in the trace
|
|
*/
|
|
def tracedTimeout(): Integer = {
|
|
val parentSpan = TRACER.spanBuilder("parent").startSpan()
|
|
val parentScope = TRACER.withSpan(parentSpan)
|
|
try {
|
|
val f: Future[String] = Future {
|
|
tracedChild("timeoutChild")
|
|
while (true) {
|
|
// never actually finish
|
|
}
|
|
"done"
|
|
}
|
|
|
|
try {
|
|
Await.result(f, 1 milliseconds)
|
|
} catch {
|
|
case e: Exception => {}
|
|
}
|
|
return 2
|
|
} finally {
|
|
parentSpan.end()
|
|
parentScope.close()
|
|
}
|
|
}
|
|
|
|
def tracedChild(opName: String): Unit = {
|
|
TRACER.spanBuilder(opName).startSpan().end()
|
|
}
|
|
}
|