On Nov 30, 2011, at 9:57 PM, Tim Allen wrote:

On Wed, Nov 30, 2011 at 01:04:27PM -0000, exarkun@twistedmatrix.com wrote:
On 04:07 am, screwtape@froup.com wrote:
If the standard Twisted logging functions automatically constructed
LogMessage instances from dict instances, it should be easy enough for
future ILogObserver implementations to do the right thing (by just
calling str(msg)). Of course, they could also do more sophisticated
things like pulling particular keys out of the message to set
observer-specific message properties (like syslog channel and severity,

Oooorrrr there could be a function that takes a dict intended to
represent a text message and returns that message as a string.

As mentioned, we already have one of those in the form of

Right, I think that's the tone all those extra letters are meant to suggest :).

The trouble is that everybody who writes
a LogObserver needs to know that it exists, and remember to call it. If
it were the __str__() method of a LogMessage object, they'd have to go
out of their way to *not* do the right thing.

I really don't like using __str__ for structured conversions.  For example, textFromEventDict has very strict error-handling behavior: it will try as hard as it can to give you something so that you don't need to do extra error handling in your log observer.  But if you can get instances of LogMessage or some derived message type or possibly application-derived message types, the behavior might change and the error-handling would be less strict and now the default log observers need to be double-careful; once in LogMessage.__str__, once in the thing that calls it because you can never really know what str(x) is going to do.

For another there's a whole nasty battery of unicode-or-bytes issues that crop up when you start using __str__.

Finally, and I'm leaving it for last because this concern is rather silly, right now log events are constructed and propagated with extremely little copying, and the copying that does happen (ahem, log contexts) needs to be reduced.  Adding a LogMessage object into the mix, even if it is a subclass of dict, means we have to, at the very least, copy all the values from msg()'s keyword arguments into a new object, rather than just propagating them to log observers.