Skip to content

Commit

Permalink
Merge branch 'main' into update/akka-actor-2.6.15
Browse files Browse the repository at this point in the history
  • Loading branch information
Jakub Czuchnowski authored Jul 12, 2021
2 parents 7eb4660 + fea4f5b commit b5aa5b9
Show file tree
Hide file tree
Showing 144 changed files with 3,888 additions and 1,696 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ target/
*.log.*
*.sh
.vscode/
.metals/
.metals/
.bloop/
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.scalac.mesmer.agent.akka.actor;

import akka.dispatch.BoundedQueueBasedMessageQueue;
import akka.dispatch.Envelope;

import java.util.concurrent.BlockingQueue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.scalac.mesmer.agent.akka.actor.impl;

import io.scalac.mesmer.core.actor.ActorCellMetrics;
import net.bytebuddy.asm.Advice;

public class ActorCellInitAdvice {

@Advice.OnMethodEnter
public static void initActorCell(@Advice.FieldValue(value = "_actorCellMetrics", readOnly = false) ActorCellMetrics metrics) {
metrics = new ActorCellMetrics();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
import akka.stream.scaladsl.Flow;
import net.bytebuddy.asm.Advice;

public class HttpExtAdvice {
public class HttpExtConnectionsAdvice {

@Advice.OnMethodEnter
public static void bindAndHandle(@Advice.Argument(value = 0, readOnly = false) Flow<HttpRequest, HttpResponse, Object> handler,
@Advice.Argument(1) String _interface,
@Advice.Argument(2) Integer port,
@Advice.This Object self) {
handler = HttpInstrumentation.bindAndHandleImpl(handler, _interface, port, (HttpExt) self);
handler = HttpInstrumentation.bindAndHandleConnectionsImpl(handler, _interface, port, (HttpExt) self);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.scalac.mesmer.agent.akka.http;

import akka.http.scaladsl.HttpExt;
import akka.http.scaladsl.model.HttpRequest;
import akka.http.scaladsl.model.HttpResponse;
import akka.stream.scaladsl.Flow;
import net.bytebuddy.asm.Advice;

public class HttpExtRequestsAdvice {
@Advice.OnMethodEnter
public static void bindAndHandle(@Advice.Argument(value = 0, readOnly = false) Flow<HttpRequest, HttpResponse, Object> handler,
@Advice.This Object self) {
handler = HttpInstrumentation.bindAndHandleRequestImpl(handler, (HttpExt) self);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package akka;

import akka.actor.Actor;
import io.scalac.mesmer.agent.akka.stream.ActorGraphInterpreterDecorator;
import io.scalac.mesmer.agent.akka.stream.impl.ActorGraphInterpreterDecorator;
import net.bytebuddy.asm.Advice;
import scala.PartialFunction;
import scala.runtime.BoxedUnit;
Expand All @@ -12,8 +12,8 @@ public class ActorGraphInterpreterAdvice {

@Advice.OnMethodExit
public static void overrideReceive(@Advice.Return(readOnly = false) PartialFunction<Object, BoxedUnit> result,
@Advice.This Actor self) {
result = ActorGraphInterpreterDecorator.addCollectionReceive(result, self);
@Advice.This Object self) {
result = ActorGraphInterpreterDecorator.addCollectionReceive(result, (Actor) self);
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package akka.stream;

import akka.stream.impl.StreamLayout;
import io.scalac.mesmer.agent.akka.stream.GraphStageIslandOps;
import io.scalac.mesmer.agent.akka.stream.impl.GraphStageIslandOps;
import net.bytebuddy.asm.Advice;

import java.util.ArrayList;
Expand Down
70 changes: 35 additions & 35 deletions agent/src/main/scala/io/scalac/mesmer/agent/Agent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@ import net.bytebuddy.agent.builder.AgentBuilder
import org.slf4j.LoggerFactory

import io.scalac.mesmer.agent.Agent.LoadingResult
import io.scalac.mesmer.core.model.SupportedModules
import io.scalac.mesmer.core.util.ModuleInfo.Modules

object Agent {

private val logger = LoggerFactory.getLogger(classOf[Agent])
def apply(head: AgentInstrumentation, tail: AgentInstrumentation*): Agent = new Agent(Set.from(head +: tail))

def apply(head: AgentInstrumentation, tail: AgentInstrumentation*): Agent = Agent((head +: tail).toSet)
val empty: Agent = new Agent(Set.empty[AgentInstrumentation])

class LoadingResult(val fqns: Seq[String]) {
class LoadingResult(val fqns: Set[String]) {
import LoadingResult.{ logger => loadingLogger }
def eagerLoad(): Unit =
fqns.foreach { className =>
Expand All @@ -38,55 +36,57 @@ object Agent {
object LoadingResult {
private val logger = LoggerFactory.getLogger(classOf[LoadingResult])

def apply(fqns: Seq[String]): LoadingResult = new LoadingResult(fqns)
def apply(fqns: Seq[String]): LoadingResult = new LoadingResult(fqns.toSet)

def apply(fqn: String, fqns: String*): LoadingResult = apply(fqn +: fqns)

def empty: LoadingResult = new LoadingResult(Seq.empty)
def empty: LoadingResult = new LoadingResult(Set.empty)
}
}

object AgentInstrumentation {

def apply(name: String, modules: SupportedModules)(
installation: (AgentBuilder, Instrumentation, Modules) => LoadingResult
def apply(name: String, tags: Set[String], deferred: Boolean)(
installation: (AgentBuilder, Instrumentation) => LoadingResult
): AgentInstrumentation =
new AgentInstrumentation(name, modules) {
def apply(builder: AgentBuilder, instrumentation: Instrumentation, modules: Modules): LoadingResult =
installation(builder, instrumentation, modules)
new AgentInstrumentation(name, tags, deferred) {
def apply(builder: AgentBuilder, instrumentation: Instrumentation): LoadingResult =
installation(builder, instrumentation)
}

}

sealed abstract case class AgentInstrumentation(name: String, instrumentingModules: SupportedModules)
extends ((AgentBuilder, Instrumentation, Modules) => LoadingResult) {
sealed abstract case class AgentInstrumentation(
name: String,
tags: Set[String],
private val deferred: Boolean
) extends ((AgentBuilder, Instrumentation) => LoadingResult)
with Equals
with Ordered[AgentInstrumentation] {

override def hashCode(): Int = name.hashCode()

override def canEqual(that: Any): Boolean = that.isInstanceOf[AgentInstrumentation]

override def equals(obj: Any): Boolean = obj match {
case that: AgentInstrumentation if that.canEqual(this) =>
tags == that.tags && name == that.name
case _ => false
}

override def hashCode(): Int = name.hashCode()
override def equals(obj: Any): Boolean = name.equals(obj) // instrumentations should be equal when name is the same
final def compare(that: AgentInstrumentation): Int = Ordering[Boolean].compare(this.deferred, that.deferred)
}

final case class Agent private (private val set: Set[AgentInstrumentation]) extends {
final case class Agent private (private[agent] val instrumentations: Set[AgentInstrumentation]) extends {
import Agent._

def ++(other: Agent): Agent = Agent(set ++ other.set)

def ++(other: AgentInstrumentation): Agent = Agent(set + other)
def ++(other: Agent): Agent = Agent(instrumentations ++ other.instrumentations)

def installOn(builder: AgentBuilder, instrumentation: Instrumentation, modules: Modules): LoadingResult =
set.flatMap { agentInstrumentation =>
val dependencies = agentInstrumentation.instrumentingModules
def ++(other: AgentInstrumentation): Agent = Agent(instrumentations + other)

val allModulesSupported = dependencies.modules.forall { module =>
modules
.get(module)
.exists(dependencies.supportedVersion(module).supports)
}
def installOn(builder: AgentBuilder, instrumentation: Instrumentation): LoadingResult =
instrumentations.toSeq.sorted.map { agentInstrumentation =>
agentInstrumentation(builder, instrumentation)

if (allModulesSupported) {
val requiredModules = modules.view.filterKeys(dependencies.modules.contains)
Some(agentInstrumentation(builder, instrumentation, requiredModules.toMap))
} else {
logger.error("Unsupported versions for instrumentation for {}", agentInstrumentation.name)
None
}
}.fold(LoadingResult.empty)(_ ++ _)
}
18 changes: 12 additions & 6 deletions agent/src/main/scala/io/scalac/mesmer/agent/Boot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@ package io.scalac.mesmer.agent

import java.lang.instrument.Instrumentation

import com.typesafe.config.ConfigFactory
import net.bytebuddy.ByteBuddy
import net.bytebuddy.agent.builder.AgentBuilder
import net.bytebuddy.dynamic.scaffold.TypeValidation

import scala.annotation.unused

import io.scalac.mesmer.agent.akka.actor.AkkaActorAgent
import io.scalac.mesmer.agent.akka.actor.AkkaMailboxAgent
import io.scalac.mesmer.agent.akka.http.AkkaHttpAgent
import io.scalac.mesmer.agent.akka.persistence.AkkaPersistenceAgent
import io.scalac.mesmer.agent.akka.stream.AkkaStreamAgent
import io.scalac.mesmer.core.util.ModuleInfo
import io.scalac.mesmer.core.util.LibraryInfo

object Boot {

//TODO better configuration specification
def premain(@unused arg: String, instrumentation: Instrumentation): Unit = {

val config = ConfigFactory.load()

val agentBuilder = new AgentBuilder.Default()
.`with`(new ByteBuddy().`with`(TypeValidation.DISABLED))
.`with`(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
Expand All @@ -27,12 +30,15 @@ object Boot {
)
.`with`(AgentBuilder.InstallationListener.StreamWriting.toSystemOut)

val allInstrumentations =
AkkaPersistenceAgent.agent ++ AkkaHttpAgent.agent ++ AkkaStreamAgent.agent ++ AkkaActorAgent.agent ++ AkkaMailboxAgent.agent
val moduleInfo = ModuleInfo.extractModulesInformation(Thread.currentThread().getContextClassLoader)
val info = LibraryInfo.extractModulesInformation(Thread.currentThread().getContextClassLoader)

val allInstrumentations = AkkaPersistenceAgent.initAgent(info, config).getOrElse(Agent.empty) ++
AkkaStreamAgent.initAgent(info, config).getOrElse(Agent.empty) ++
AkkaHttpAgent.initAgent(info, config).getOrElse(Agent.empty) ++
AkkaActorAgent.initAgent(info, config).getOrElse(Agent.empty)

allInstrumentations
.installOn(agentBuilder, instrumentation, moduleInfo)
.installOn(agentBuilder, instrumentation)
.eagerLoad()

}
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit b5aa5b9

Please sign in to comment.