How print all actors in akka system?

后端 未结 3 1464
醉梦人生
醉梦人生 2021-01-31 05:07

I have created akka system. Suppose there are some actors in it. How I can print all actors from akka system with their path? (for debug purposes)

相关标签:
3条回答
  • 2021-01-31 05:45

    ActorSystem has private method printTree, that you can use for debugging.

    1) Private method caller (from https://gist.github.com/jorgeortiz85/908035):

    class PrivateMethodCaller(x: AnyRef, methodName: String) {
      def apply(_args: Any*): Any = {
        val args = _args.map(_.asInstanceOf[AnyRef])
    
        def _parents: Stream[Class[_]] = Stream(x.getClass) #::: _parents.map(_.getSuperclass)
    
        val parents = _parents.takeWhile(_ != null).toList
        val methods = parents.flatMap(_.getDeclaredMethods)
        val method = methods.find(_.getName == methodName).getOrElse(throw new IllegalArgumentException("Method " + methodName + " not found"))
        method.setAccessible(true)
        method.invoke(x, args: _*)
      }
    }
    
    class PrivateMethodExposer(x: AnyRef) {
      def apply(method: scala.Symbol): PrivateMethodCaller = new PrivateMethodCaller(x, method.name)
    }
    

    2) Usage

    val res = new PrivateMethodExposer(system)('printTree)()
    println(res)
    

    Will print:

    -> / LocalActorRefProvider$$anon$1 class akka.actor.LocalActorRefProvider$Guardian status=0 2 children
       ⌊-> system LocalActorRef class akka.actor.LocalActorRefProvider$SystemGuardian status=0 3 children
       |   ⌊-> deadLetterListener RepointableActorRef class akka.event.DeadLetterListener status=0 no children
       |   ⌊-> eventStreamUnsubscriber-1 RepointableActorRef class akka.event.EventStreamUnsubscriber status=0 no children
       |   ⌊-> log1-Logging$DefaultLogger RepointableActorRef class akka.event.Logging$DefaultLogger status=0 no children
       ⌊-> user LocalActorRef class akka.actor.LocalActorRefProvider$Guardian status=0 1 children
    ...
    

    Beware, it can cause OOM If you have a lot of actors.

    0 讨论(0)
  • 2021-01-31 05:49

    According to the documentation you can use ActorSelection with a wildcard * to make actors send identifying messages. You can have an actor that collect the ActorRefs.

    As mentioned by @chris-martin only actors that are not currently busy will send. A very simple actor:

    // make all the available actor to send an identifying message
    public void freeActors()
    {
      ActorSelection selection =
        getContext().actorSelection("/user/*");
      selection.tell(new Identify(identifyId), getSelf());
    }
    
    ...
    // collect responses
    @Override
    public void onReceive(Object message) {
      if (message instanceof ActorIdentity) {
        ActorIdentity identity = (ActorIdentity) message;
        // get the ref of the sender 
        ActorRef ref = identity.getRef();
        // the sender is up and available
       ...
    

    EDIT: I know this is for Java, but it seemed helpful to me.

    0 讨论(0)
  • 2021-01-31 05:51

    This reply by Roland Kuhn suggests that this isn't a completely trivial problem, but you can get pretty close (for actors that will reply to messages in a reasonable time) using the Identify-ActorIdentity request-response protocol that all actors obey.

    Some untested code thrown together to illustrate the idea:

    import akka.actor._
    
    def receive = {
        case 'listActors =>
          context.actorSelection("/user/*") ! Identify()
    
        case path: ActorPath =>
          context.actorSelection(path / "*") ! Identify()
    
        case ActorIdentity(_, Some(ref)) =>
          log.info("Got actor " + ref.path.toString)
          self ! ref.path
    }
    
    0 讨论(0)
提交回复
热议问题