Hi,
> On Apr 27, 2016, at 10:43 AM, Norbert Hartl <[email protected]> wrote: > > Denis, > >> Am 26.04.2016 um 17:28 schrieb Denis Kudriashov <[email protected]>: >> >> Hi Tudor. >> >> 2016-04-26 15:36 GMT+02:00 Tudor Girba <[email protected]>: >> >> > Let's think about logging API to log any object in the system. Most >> > natural way is just send message #log to object itself: >> > >> > anObject log >> > >> > It would be nice replacement for Object>>logCr. >> >> This type of usage should be discouraged in my opinion. We should instead >> encourage people to use typed logging signals, like we should also >> discourage people from using >> self error: ‘a magic string here’. >> >> >> > But when we log some information we usually want to log it with little >> > remark, importance level and (most important) timestamp. This information >> > is kind of standard for logging domain. But it requires much more methods >> > for logging API. >> > So we need extra information to put together with objects: >> > • timestamp >> > • user message >> > • importance level (debug, info, error, etc.) >> >> Please do not do that. This might make sense for C or Java (although it does >> not), but we have objects and we should filter based on those without >> relying on a rigid system based on random levels. Please. >> >> Before I start to think about logging I was agree with you. Now I am not. >> This kind of information belongs to logging domain. It can be retrieved from >> application objects as default values but at the end it should be explicit >> part of log entries. We can read it in logs for every record to realize when >> and why object was added to log, what this record is about. >> >> And you say let's replace this "log object context" information with first >> class entities "typed signals". It means that for any possible case when I >> want to put something in log I should create class for new signal. It's just >> not practical. >> Beacon introduce WrapperSignal to solve it. But it only provides target and >> timestamp. What I should do if I want to put little remark for my object? >> And what if I want to put little remark for ThisContextSignal? >> >> My idea that logging should be as simple as possible and we not need another >> "everything is signal" concept here: it is restriction. Everything is >> object. And every object should be able to log. >> >> And about random log levels. Their purpose is to mark log entries with >> importance level which is useful to explore logs. >> Imaging we have system which produce some events and we log them. (My and >> your approaches allow it. Only difference that in my approach this event >> will be part of log entry (as composition) and with your approach this event >> will be log entry itself). >> Now imagine that we need to explore some problem situation when particular >> events are appeared but they should not. I would try to find wrong places in >> code where events can be signalled and I would log them their. >> With my approach I will log them with specific importance level (#warning) >> and specific message to distinguish them from normal events. With my API it >> is super easy. >> With your approach I will need to create new classes to signal this >> situation. >> Also my approach allows me to configure in advance my application to put >> warnings in separate log. So I will not need to change app configs to >> simplify experiment. I will just deploy new code with extra logging and wait >> results in ready to use log. >> >> My proposals are not opposite to your. I just not put extra restrictions. >> Beacon can be based on top of it but not vice versa. > > I must confess I cannot follow you completely. What we were/are talking about > is that the assumption a logging entry needs timestamp, log level and such is > not appropriate. If you have legacy syslog style logging in mind it appears > natural but for a lot of use cases it is not. Yes. > Even if you could say that a timestamp is part of the logging domain it is > not said if that timestamp needs to be part of the log object or the logger > consuming this object. This is a good point. I still see it closer to the event than to the logger. > This question arises for every quality of a logging object. Even the logging > level could be some behavioral quality that a logger matches to log levels. > Contrary to this is logging thisContext which has to be done in the log > object. Yes. I think it would be worthwhile to think about a composition mechanism. We could potentially use decorators for capturing extra information in the log event object. > I think the hard part is the way of distribution of log objects and filtering > of them. While the former is being discussed with Beacon the latter is mostly > ignored while being really important. Not having default qualities of a log > object is good on one hand but on the other hand the filtering is much > harder. I agree that we would benefit from an instance-based filtering mechanism, but I do not see why this is harder in Announcement. However we do it, it can be added to Announcements and it is available for all purposes (not just logging). Maybe I am missing something. > In SystemLogger we didn't go far enough at first. The Log class contained > level and such. That was the reason for me to split it into BasicLog > consisting of timestamp and a message object and Log which contains the extra > qualities. Nowadays I think you should be able to use any object as log > object. The provided classes are just helpers. A composed object that has > timestamp, level and a message object is a good utility but not a > requirement. We need to support all of these. And so I would object against > putting a lot of protocol in the Object class. In SystemLogger you have > > Object>>#asLog > ^ self class newLog message: self One thing that I think is misleading (I remember it took me some minutes to wrap my head around it) is the way SystemLogger uses the term “log”. In English, log denotes all entries (a log book), but in SystemLogger it is used to denote one event. In any case, having an as* pattern (like it exists in Beacon) is the way to go. > Object class>>#newLog > ^ self logClass new > > Object class>>#logClass > "Hook supporting the redefinition by object of their associated log. > When using myObject asLog emit, the logClass will be used and myObject > will be passed as message argument." > > ^ Log This is another thing that is different from Beacon. I see the logging as a description of an event that is worthwhile capturing. This event has a strategy to record things. For example, when you capture an exception you might want to capture the complete context including the sender objects, or just the methods from the stack. This decision is tied to the Exception, but depends on the logging place. That is why I think we should not invest much in the pattern of hardcoding the strategy with the object. So, from this point of view, I would not want to pursue #logClass. > So assuming the Log class would not contain log levels but SysLog would do > you could easily override #logClass in your domain object and use it this way > > MyDomainClass class>>#logClass > ^ SysLog > > myDomainObject asLog > warning; > emit > > This way we do not need to pollute Object with a lot of methods that are > tight to one use case. The call to #warning could be something else that only > depends on the Log class you want to use. Yes. > So to me the discussion about Log classes is not very helpful. We can have > dedicated log classes like the stack capturing one but also one that is > composed of the message object and certain qualities. If you would have a > WrappedSyslogSignal you can have a log object that is composed and syslog > aware by providing log levels. I would actually like to invest in building a composition mechanism. This would allow us to compose logging objects with the information we would like to have. > Again I think the hard part is to have flexible logging and still be able to > filter it. I would like to be able to attach a handful of loggers and be sure > the loggers get the right set of log objects they are interested in. Do you have a concrete set of examples that you would like to see working? I think it would be useful to have a set of these concrete use cases to catch different design decisions against them. I have some cases and I will try to summarize them, but after the release of Pharo. Cheers, Doru > Norbert > > > > > -- www.tudorgirba.com www.feenk.com "If you can't say why something is relevant, it probably isn't."
