Welcome, guest | Sign In | My Account | Store | Cart

Sometimes it is convenient emit a log line only if the log message was different compared to previous message. However, it is also good to log a line at least every n seconds so that user knows the system is working and has not hanged. These ideas are combined in this very simple recipe.

Python, 49 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import time

class TerseLogger:

    def __init__(self, max_silent_time=60, display_time=False):

        self.prev_msg = None
        self.last_msg_time = 0
        self.max_silent_time = max_silent_time

        self.display_time = display_time

    # yeah - emit is actually a bad name because it doesn't emit every time...
    def emit(self, msg):

        now = time.time()
        # actually print message if either a) or b) applies
        # a) it is different from previous message
        # b) max_silent_time seconds have passed since last message

        if self.prev_msg != msg \
               or now - self.last_msg_time >= self.max_silent_time:

            if self.display_time:
                print "%d %s" % (now, msg)
            else:
                print msg

            self.prev_msg = msg
            self.last_msg_time = now


if __name__ == '__main__':

    obj = TerseLogger(display_time=True)

    messages = ('cat', 'dog', 'cat', 'cat', 'penguin')

    print "message is not printed if it was the same as previous message"
    for msg in messages:
        obj.emit(msg)

    obj = TerseLogger(1, display_time=True)

    print ("all messages are printed because max_silent_time "
           "was set to 1 second and we sleep 2 seconds after each iteration")
    for msg in messages:
        obj.emit(msg)
        time.sleep(2)

The main idea is to avoid log files of the form

<pre> ... 23.02.05 11.23.21 updating repository.. 23.02.05 11.23.22 updating repository.. 23.02.05 11.23.23 updating repository.. 23.02.05 11.23.24 updating repository.. 23.02.05 11.23.25 updating repository.. 23.02.05 11.23.26 updating repository.. 23.02.05 11.23.27 updating repository.. 23.02.05 11.23.28 updating repository.. 23.02.05 11.23.29 completed. </pre>

and rather have

<pre> ... 23.02.05 11.22.24 updating repository.. 23.02.05 11.23.24 updating repository.. 23.02.05 11.24.24 updating repository.. 23.02.05 11.24.37 completed. </pre>

(max_silent_time would be 60 seconds in excerpt above)

Also, it would be probably more handy to add a message formatter method which takes actual contents and writes message to user-specified stream (stdout, stderr, file, socket etc), and base class would offer a default formatter. Thus user-defined loggers could just derive from the base class overriding formatter() method.