Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# (c) Stefan Countryman, 2019
3import sys
4from time import sleep
5import ipywidgets as widgets
6from IPython.display import display
7from pathlib import Path
8from llama.utils import LOGDIR
10# docs at https://ipywidgets.readthedocs.io/en/latest/examples/Output%20Widget.html
12logs = Path(LOGDIR)
13CONTINUE = [True]
14READ_SIZE = 2000
17def setup_tail_widgets():
18 logwidg = widgets.Select(
19 options=[(x.name, x) for x in logs.iterdir() if x.is_file()],
20 index=0,
21 description="Log file:",
22 disabled=False,
23 )
24 lineswidg = widgets.IntText(
25 value=10,
26 description='Num lines:',
27 disabled=False
28 )
29 follow = widgets.Checkbox(
30 value=True,
31 description='Follow output',
32 disabled=False
33 )
34 submit = widgets.Button(
35 description='Show log',
36 disabled=False,
37 button_style='', # 'success', 'info', 'warning', 'danger' or ''
38 tooltip='Print the last "Num lines" lines of the selected logfile.',
39 icon='',
40 )
41 clear = widgets.Button(
42 description='Clear output',
43 disabled=False,
44 button_style='', # 'success', 'info', 'warning', 'danger' or ''
45 tooltip='Clear the output where logs have been printing.',
46 icon='',
47 )
48 #stop = widgets.Button(
49 # description='Stop showing',
50 # disabled=False,
51 # button_style='',
52 # tooltip='Stop printing logs',
53 # icon='',
54 #)
55 output = widgets.Output(layout={'border': '2px solid green'})
58 def onclick(button):
59 """Print the last ``lineswidg.value`` lines of ``logwidg.value`` and then
60 keep reading more lines and printing them as they become available."""
61 CONTINUE[0] = True
62 prevlines = lineswidg.value + 1
63 logpath = logwidg.value
64 with output:
65 if prevlines < 0:
66 print("Choose a value greater than 1 for Num lines.")
67 return
68 with logpath.open('rb') as f:
69 # seek back till we find
70 end = f.seek(0, 2)
71 if end <= READ_SIZE:
72 cursor = f.seek(0, 0)
73 else:
74 cursor = f.seek(-READ_SIZE, 1)
75 lines_scanned = 0
76 while cursor > 0:
77 buf = f.read(READ_SIZE)
78 newlines = buf.split(b'\n')
79 lines_scanned += len(newlines) - 1
80 if lines_scanned >= prevlines:
81 cursor += len(
82 b'\n'.join(newlines[:lines_scanned-prevlines+1])
83 ) + 1
84 break
85 cursor -= READ_SIZE
86 f.seek(cursor)
87 else:
88 cursor = 0
89 f.seek(cursor)
90 try:
91 if not follow.value:
92 sys.stdout.write(f.read(end-cursor))
93 raise KeyboardInterrupt()
94 while CONTINUE[0]:
95 nextline = f.readline()
96 while nextline and CONTINUE[0]:
97 sys.stdout.write(nextline)
98 nextline = f.readline()
99 sleep(0.3)
100 except KeyboardInterrupt:
101 print(f"~~~~~~~~~~~< DONE PRINTING {logpath} >~~~~~~~~~~~")
103 #def stopclick(button):
104 # with output:
105 # print(f"CONTINUE={CONTINUE}")
106 # print("Setting CONTINUE[0]=False")
107 # CONTINUE[0] = False
108 # print(f"New value: CONTINUE={CONTINUE}")
110 submit.on_click(onclick)
111 clear.on_click(lambda _x: output.clear_output())
112 #stop.on_click(stopclick)
114 display(logwidg)
115 display(lineswidg)
116 display(follow)
117 display(submit)
118 display(clear)
119 #display(stop)
120 display(output)