Skip to content

Commit e0844b7

Browse files
authored
rollback Future instrumentation to Kamon 1.x behavior (#1035)
1 parent 418d066 commit e0844b7

File tree

9 files changed

+287
-167
lines changed

9 files changed

+287
-167
lines changed

instrumentation/kamon-akka-http/src/main/resources/reference.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ kanela.modules {
238238
name = "Akka HTTP Instrumentation"
239239
description = "Provides context propagation, distributed tracing and HTTP client and server metrics for Akka HTTP"
240240

241+
# Add "kamon.instrumentation.akka.http.FastFutureInstrumentation" to the instrumentation list if you need to
242+
# use the Future Chaining instrumentation in Kamon 2.2.x. It will be fully removed in Kamon 2.3.0.
241243
instrumentations = [
242244
"kamon.instrumentation.akka.http.AkkaHttpServerInstrumentation"
243245
"kamon.instrumentation.akka.http.AkkaHttpClientInstrumentation"

instrumentation/kamon-akka-http/src/main/scala-2.11/kamon/instrumentation/akka/http/AkkaHttpServerInstrumentation.scala

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class AkkaHttpServerInstrumentation extends InstrumentationBuilder {
7878
.intercept(method("redirect"), classOf[ResolveOperationNameOnRouteInterceptor])
7979
.intercept(method("failWith"), classOf[ResolveOperationNameOnRouteInterceptor])
8080

81+
}
82+
83+
class FastFutureInstrumentation extends InstrumentationBuilder {
8184

8285
/**
8386
* This allows us to keep the right Context when Futures go through Akka HTTP's FastFuture and transformantions made
@@ -304,7 +307,9 @@ object FastFutureTransformWithAdvice {
304307
catch { case NonFatal(e) => FastFuture.failed(e) }
305308

306309
// If we get a FulfilledFuture or ErrorFuture, those will have the HasContext mixin,
307-
// otherwise we are getting a regular Future which has the context mixed into its value.
310+
// otherwise we are getting a regular Future that might have a context mixed into its
311+
// value if the Future Chaining instrumentation is manually enabled (it was deprecated
312+
// in Kamon 2.1.21).
308313
if(future.isInstanceOf[HasContext])
309314
zuper.call()
310315
else {
@@ -316,18 +321,25 @@ object FastFutureTransformWithAdvice {
316321
case Failure(e) => p completeWith strictTransform(e, f)
317322
}(ec)
318323
p.future
324+
319325
case Some(value) =>
320-
// This is possible because of the Future's instrumentation
321-
val futureContext = value.asInstanceOf[HasContext].context
322-
val scope = Kamon.storeContext(futureContext)
326+
value match {
327+
case hc: HasContext =>
328+
// The Future's value (Try[A]) might have a Context stored if the
329+
// Future Chaining instrumentation is enabled.
330+
val scope = Kamon.storeContext(hc.context)
331+
332+
val transformedFuture = value match {
333+
case Success(a) => strictTransform(a, s)
334+
case Failure(e) => strictTransform(e, f)
335+
}
336+
337+
scope.close()
338+
transformedFuture
323339

324-
val transformedFuture = value match {
325340
case Success(a) => strictTransform(a, s)
326341
case Failure(e) => strictTransform(e, f)
327342
}
328-
329-
scope.close()
330-
transformedFuture
331343
}
332344
}
333345
}

instrumentation/kamon-akka-http/src/main/scala-2.12/kamon/instrumentation/akka/http/AkkaHttpServerInstrumentation.scala

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,18 @@ class AkkaHttpServerInstrumentation extends InstrumentationBuilder {
9696
.intercept(method("redirect"), classOf[ResolveOperationNameOnRouteInterceptor])
9797
.intercept(method("failWith"), classOf[ResolveOperationNameOnRouteInterceptor])
9898

99+
/**
100+
* Akka-http 10.1.x compatibility.
101+
*/
102+
103+
onType("akka.http.scaladsl.Http2Ext")
104+
.advise(method("bindAndHandleAsync") and isPublic(), classOf[Http2ExtBindAndHandleAdvice])
105+
}
106+
107+
class FastFutureInstrumentation extends InstrumentationBuilder {
99108

100109
/**
101-
* This allows us to keep the right Context when Futures go through Akka HTTP's FastFuture and transformantions made
110+
* This allows us to keep the right Context when Futures go through Akka HTTP's FastFuture and transformations made
102111
* to them. Without this, it might happen that when a Future is already completed and used on any of the Futures
103112
* directives we might get a Context mess up.
104113
*/
@@ -110,14 +119,6 @@ class AkkaHttpServerInstrumentation extends InstrumentationBuilder {
110119

111120
onType("akka.http.scaladsl.util.FastFuture$")
112121
.intercept(method("transformWith$extension1"), FastFutureTransformWithAdvice)
113-
114-
115-
/**
116-
* Akka-http 10.1.x compatibility.
117-
*/
118-
119-
onType("akka.http.scaladsl.Http2Ext")
120-
.advise(method("bindAndHandleAsync") and isPublic(), classOf[Http2ExtBindAndHandleAdvice])
121122
}
122123

123124
trait HasMatchingContext {
@@ -329,7 +330,9 @@ object FastFutureTransformWithAdvice {
329330
catch { case NonFatal(e) => FastFuture.failed(e) }
330331

331332
// If we get a FulfilledFuture or ErrorFuture, those will have the HasContext mixin,
332-
// otherwise we are getting a regular Future which has the context mixed into its value.
333+
// otherwise we are getting a regular Future that might have a context mixed into its
334+
// value if the Future Chaining instrumentation is manually enabled (it was deprecated
335+
// in Kamon 2.1.21).
333336
if(future.isInstanceOf[HasContext])
334337
zuper.call()
335338
else {
@@ -341,18 +344,25 @@ object FastFutureTransformWithAdvice {
341344
case Failure(e) => p completeWith strictTransform(e, f)
342345
}(ec)
343346
p.future
347+
344348
case Some(value) =>
345-
// This is possible because of the Future's instrumentation
346-
val futureContext = value.asInstanceOf[HasContext].context
347-
val scope = Kamon.storeContext(futureContext)
349+
value match {
350+
case hc: HasContext =>
351+
// The Future's value (Try[A]) might have a Context stored if the
352+
// Future Chaining instrumentation is enabled.
353+
val scope = Kamon.storeContext(hc.context)
354+
355+
val transformedFuture = value match {
356+
case Success(a) => strictTransform(a, s)
357+
case Failure(e) => strictTransform(e, f)
358+
}
359+
360+
scope.close()
361+
transformedFuture
348362

349-
val transformedFuture = value match {
350363
case Success(a) => strictTransform(a, s)
351364
case Failure(e) => strictTransform(e, f)
352365
}
353-
354-
scope.close()
355-
transformedFuture
356366
}
357367
}
358368
}

instrumentation/kamon-akka-http/src/main/scala-2.13/kamon/instrumentation/akka/http/AkkaHttpServerInstrumentation.scala

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ class AkkaHttpServerInstrumentation extends InstrumentationBuilder {
7979
.intercept(method("failWith"), classOf[ResolveOperationNameOnRouteInterceptor])
8080

8181

82+
/**
83+
* Akka-http 10.1.x compatibility.
84+
*/
85+
86+
onType("akka.http.scaladsl.Http2Ext")
87+
.advise(method("bindAndHandleAsync") and isPublic(), classOf[Http2ExtBindAndHandleAdvice])
88+
}
89+
90+
class FastFutureInstrumentation extends InstrumentationBuilder {
91+
8292
/**
8393
* This allows us to keep the right Context when Futures go through Akka HTTP's FastFuture and transformantions made
8494
* to them. Without this, it might happen that when a Future is already completed and used on any of the Futures
@@ -92,13 +102,6 @@ class AkkaHttpServerInstrumentation extends InstrumentationBuilder {
92102

93103
onType("akka.http.scaladsl.util.FastFuture$")
94104
.intercept(method("transformWith$extension").and(takesArguments(4)), FastFutureTransformWithAdvice)
95-
96-
/**
97-
* Akka-http 10.1.x compatibility.
98-
*/
99-
100-
onType("akka.http.scaladsl.Http2Ext")
101-
.advise(method("bindAndHandleAsync") and isPublic(), classOf[Http2ExtBindAndHandleAdvice])
102105
}
103106

104107
trait HasMatchingContext {
@@ -328,18 +331,25 @@ object FastFutureTransformWithAdvice {
328331
case Failure(e) => p completeWith strictTransform(e, f)
329332
}(ec)
330333
p.future
334+
331335
case Some(value) =>
332-
// This is possible because of the Future's instrumentation
333-
val futureContext = value.asInstanceOf[HasContext].context
334-
val scope = Kamon.storeContext(futureContext)
336+
value match {
337+
case hc: HasContext =>
338+
// The Future's value (Try[A]) might have a Context stored if the
339+
// Future Chaining instrumentation is enabled.
340+
val scope = Kamon.storeContext(hc.context)
341+
342+
val transformedFuture = value match {
343+
case Success(a) => strictTransform(a, s)
344+
case Failure(e) => strictTransform(e, f)
345+
}
346+
347+
scope.close()
348+
transformedFuture
335349

336-
val transformedFuture = value match {
337350
case Success(a) => strictTransform(a, s)
338351
case Failure(e) => strictTransform(e, f)
339352
}
340-
341-
scope.close()
342-
transformedFuture
343353
}
344354
}
345355
}

instrumentation/kamon-akka-http/src/test/scala/kamon/akka/http/FastFutureInstrumentationSpec.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,16 @@ import scala.util.Try
1818

1919
class FastFutureInstrumentationSpec extends WordSpec with Matchers {
2020

21-
"the FastFuture instrumentation" should {
21+
/**
22+
* DEPRECATED
23+
*
24+
* This spec is ignored since Kamon 2.2.0, along with the deprecation of the Future Chaining instrumentation, and
25+
* should be completely removed before releasing Kamon 2.3.0.
26+
*
27+
* We are keeping this spec only for the rare case that we might need to fix a bug on the Future Chaining
28+
* instrumentation while we keep it in maintenance mode.
29+
*/
30+
"the FastFuture instrumentation" ignore {
2231
"keep the Context captured by the Future from which it was created" when {
2332
"calling .map/.flatMap/.onComplete and the original Future has not completed yet" in {
2433
val completeSignal = new CountDownLatch(1)

instrumentation/kamon-executors/src/main/resources/reference.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ kanela.modules {
2727
"^com.sun.tools.*",
2828
"^sbt.internal.*",
2929
"^com.intellij.rt.*",
30-
"^scala.concurrent.*",
3130
"^org.jboss.netty.*",
3231
"^com.google.common.base.internal.Finalizer",
3332
"^kamon.module.*",

instrumentation/kamon-scala-future/src/main/resources/reference.conf

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@ kamon.instrumentation.futures.scala {
2121
}
2222

2323
kanela.modules {
24+
executor-service {
25+
within += "scala.concurrent.impl.CallbackRunnable"
26+
within += "scala.concurrent.impl.Future\\$PromiseCompletingRunnable"
27+
within += "scala.concurrent.impl.Promise\\$Transformation"
28+
}
2429

2530
scala-future {
26-
name = "Scala Future Instrumentation"
31+
name = "Scala Future Chaining Instrumentation (Deprecated)"
2732
order = 1
33+
enabled = false
2834
description = "Deprecated since Kamon 2.1.21, will be removed in Kamon 2.3.0. Provides automatic context propagation to the thread executing a Scala Future's body and callbacks"
2935
instrumentations = [
3036
"kamon.instrumentation.futures.scala.FutureChainingInstrumentation"

0 commit comments

Comments
 (0)