kquick / Thespian

Python Actor concurrency library
MIT License
189 stars 24 forks source link

'MultiProcManager' object has no attribute 'logger' #69

Closed htarnacki closed 3 years ago

htarnacki commented 3 years ago
    actor_system = ActorSystem(
        systemBase="multiprocTCPBase",
        logDefs=logging_configuration)
class Logger(Actor):

    def receiveMessage(self, message, sender):
        self.logger().info(f'Logger: message received: {message}')
        self.send(sender, 'Hello, World!')

thespian/actors.py", line 235, in logger return self._myRef.logger(name)

AttributeError: 'MultiProcManager' object has no attribute 'logger'

thespian-3.10.1

kquick commented 3 years ago

Hi @htarnacki

You didn't provide much context, so I apologize if the following does not address your issue:

Each Actor is it's own class and not a subclass of the ActorSystem, so to access the logging, you would use the logging globals, or you would need to initialize a logging instance for your actor manually.

    import logging

    class Logger(Actor):
        def receiveMessage(self, message, sender):
            logging.info(f'Logger: message received: {message}')
            self.send(sender, 'Hello, World!')

As a minor note, I would recommend you use the older %s formatting in log messages, so your logging line would be:

    logging.info('Logger: message received: %s', message)

The reason I'd recommend this is that the conversion of the arguments to string for for substitution only occurs if the logging message is going to be written (i.e. not filtered out by severity or some other means). This can be a performance benefit by saving numerous calls to various objects' .str() method when the output would just be discarded.

htarnacki commented 3 years ago

Hi @kquick I finally try to familiarize with the Thespian and it's API. So i started to read documentation and experimenting with the code. In docs i see such a statement:

Log output generated by Actors may automatically have an "actorAddress" attribute added, which can be referenced by the log formatter (in the same manner as the standard attributes such as "levelname" and "message").

Based on this statement i thought that there must be some base actor class method for logging purposes which makes this automatic injection of field "actorAddress". I started searching and found:

def logger(self, name=None):
        return self._myRef.logger(name)

in class Actor

So i tried to run this code:

class Logger(Actor):

    def receiveMessage(self, message, sender):
        self.logger().info(f'Logger: message received: {message}')

and it worked exactly as i thought:

2020-11-03 07:57:51,481 INFO => Logger: message received: WakeupMessage(1, None) [QueueListener.py:16] [ActorAddr-/A~a] in opposition to logging by using logging globals which do not do this automatic injection:


from logging import info
class QueueListener(IActor):
def receiveMessage(self, message, sender):
    info(f'Actor "QueueListener" message received: {message}')


> 2020-11-03 07:57:51,481 INFO  =>  Actor "QueueListener" message received: WakeupMessage(1, None)  [QueueListener.py:15]

but after that i changed actor system implementation from "simpleSystemBase" to "multiprocTCPBase" and the code suddenly stopped working. So i thought it must be a bug:

> AttributeError: 'MultiProcManager' object has no attribute 'logger'

---------

> As a minor note, I would recommend you use the older %s formatting in log messages, so your logging line would be:

Good point. Thanks ;-)
kquick commented 3 years ago

Thanks for the additional information, that is indeed a bug (actually more of an incomplete implementation that wasn't caught before). I will work on getting this supported in a future release; until then, does the method I described in my previous reply work for you?

Also, I think you've already seen this, but in case you have not, https://thespianpy.com/doc/using.html#hH-ce55494c-dd7a-4258-a1e8-b090c3bbb1e6 provides additional information about logging configuration.

kquick commented 3 years ago

Fixed in release 3.10.2. Thanks for the report!