Skip to content

Commit

Permalink
Automatic instrumentation for Scala's global execution context (#1280)
Browse files Browse the repository at this point in the history
* instrument scala global context executor service

* Add scala global instrumentation context advice for Scala 3

---------

Co-authored-by: Bojan Dunaj <[email protected]>
  • Loading branch information
solnaranu and Bojan Dunaj authored Jun 9, 2023
1 parent c3f0655 commit fc7a137
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ kanela.modules {
Context propagation on serveral situations, including Scala, Twitter and Scalaz Futures"""

instrumentations = [
"kamon.instrumentation.executor.ExecutorTaskInstrumentation"
"kamon.instrumentation.executor.ExecutorTaskInstrumentation",
"kamon.instrumentation.executor.ScalaGlobalExecutionContextInstrumentation"
]

exclude = [
Expand All @@ -33,6 +34,11 @@ kanela.modules {
"^kamon.instrumentation.executor.ExecutorInstrumentation.*",
"^kanela.agent.*"
]

within = [
"scala.concurrent.ExecutionContext\\$",
"scala.concurrent.ExecutionContext\\$Implicits\\$"
]
}

executor-service-capture-on-submit {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2013-2023 The Kamon Project <https://kamon.io>
*
* 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 kamon.instrumentation.executor;

import kanela.agent.libs.net.bytebuddy.asm.Advice;
import scala.concurrent.ExecutionContext$;
import scala.concurrent.impl.ExecutionContextImpl;

import java.util.concurrent.ExecutorService;

import static kanela.agent.libs.net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;

final class ScalaGlobalExecutionContextAdvice {

@Advice.OnMethodExit
public static void onExit(@Advice.Return(readOnly = false, typing = DYNAMIC) ExecutionContextImpl returnValue) {
ExecutorService instrumented = ExecutorInstrumentation.instrument((ExecutorService) returnValue.executor(), "scala-global-execution-context");
returnValue = new ExecutionContextImpl(instrumented, ExecutionContext$.MODULE$.defaultReporter());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2013-2023 The Kamon Project <https://kamon.io>
*
* 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 kamon.instrumentation.executor;

import kanela.agent.libs.net.bytebuddy.asm.Advice;
import scala.concurrent.ExecutionContext;
import scala.concurrent.impl.ExecutionContextImpl;

import java.util.concurrent.ExecutorService;

import static kanela.agent.libs.net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;

final class ScalaGlobalExecutionContextAdvice {

@Advice.OnMethodExit
public static void onExit(@Advice.Return(readOnly = false, typing = DYNAMIC) ExecutionContextImpl returnValue) {
ExecutorService instrumented = ExecutorInstrumentation.instrument((ExecutorService) returnValue.executor(), "scala-global-execution-context");
returnValue = new ExecutionContextImpl(instrumented, ExecutionContext.defaultReporter());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2013-2023 The Kamon Project <https://kamon.io>
*
* 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 kamon.instrumentation.executor;

import kanela.agent.libs.net.bytebuddy.asm.Advice;
import scala.concurrent.ExecutionContext;
import scala.concurrent.ExecutionContextExecutorService;

import java.util.concurrent.ExecutorService;

import static kanela.agent.libs.net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;

final class ScalaGlobalExecutionContextAdvice {
@Advice.OnMethodExit
public static void onExit(@Advice.Return(readOnly = false, typing = DYNAMIC) ExecutionContextExecutorService returnValue) {
ExecutorService instrumented = ExecutorInstrumentation.instrument(returnValue, "scala-global-execution-context");
returnValue = ExecutionContext.fromExecutorService(instrumented);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2013-2023 The Kamon Project <https://kamon.io>
*
* 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 kamon.instrumentation.executor;

import kanela.agent.libs.net.bytebuddy.asm.Advice;
import scala.concurrent.ExecutionContext;
import scala.concurrent.ExecutionContextExecutorService;

import java.util.concurrent.ExecutorService;

import static kanela.agent.libs.net.bytebuddy.implementation.bytecode.assign.Assigner.Typing.DYNAMIC;

final class ScalaGlobalExecutionContextAdvice {
@Advice.OnMethodExit
public static void onExit(@Advice.Return(readOnly = false, typing = DYNAMIC) ExecutionContextExecutorService returnValue) {
ExecutorService instrumented = ExecutorInstrumentation.instrument(returnValue, "scala-global-execution-context");
returnValue = ExecutionContext.fromExecutorService(instrumented);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2013-2023 The Kamon Project <https://kamon.io>
*
* 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 kamon.instrumentation.executor

import kanela.agent.api.instrumentation.InstrumentationBuilder
class ScalaGlobalExecutionContextInstrumentation extends InstrumentationBuilder {

onTypes("scala.concurrent.ExecutionContext$", "scala.concurrent.ExecutionContext$Implicits$")
.advise(method("global$lzycompute"), classOf[ScalaGlobalExecutionContextAdvice])
}

0 comments on commit fc7a137

Please sign in to comment.