Index

lognestmonster / 6177dd6

A general-purpose single-header C logging library and parser for event-based logs. (Incomplete)

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
9407 Sep 2019 22:046177dd6updatesJosh Stockin1138N

Blob @ lognestmonster / parser / parse.py

application/x-python8115 bytesdownload raw
1# lognestmonster Copyright (c) 2019 Joshua 'joshuas3' Stockin
2# <https://github.com/JoshuaS3/lognestmonster/>.
3
4
5# This file is part of lognestmonster.
6
7# lognestmonster is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11
12# lognestmonster is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16
17# You should have received a copy of the GNU General Public License
18# along with lognestmonster. If not, see <https://www.gnu.org/licenses/>.
19
20import os
21import sys
22import time
23from utils import *
24from format import *
25from text import *
26from args import *
27from parseargs import *
28from read import *
29
30class Parser:
31 screen = None
32 clines = None
33 ccols = None
34 lines = None
35 def __init__(self):
36 self.screen = curses_window()
37 self.get_size()
38
39 def get_size(self):
40 size = term_size()
41 self.clines = size[0]
42 self.ccols = size[1]
43
44 def redraw(self):
45 self.get_size()
46 curses_clear(self.screen)
47 l = 0
48 for line in self.lines:
49 if l == self.clines: break
50 self.screen.move(l, 0)
51 line_len = 0
52 for string in line:
53 # ("content string", "attributes string")
54 content = string[0]
55
56 self.screen.attrset(0)
57
58 try:
59 attr = string[1]
60 except:
61 attr = ""
62
63 if "RESET" in attr: # set curses attributes based on attributes string
64 self.screen.attron(curses.color_pair(0))
65 else:
66 if "BLACK" in attr:
67 self.screen.attron(curses.color_pair(1))
68 if "BLUE" in attr:
69 self.screen.attron(curses.color_pair(2))
70 if "CYAN" in attr:
71 self.screen.attron(curses.color_pair(3))
72 if "GREEN" in attr:
73 self.screen.attron(curses.color_pair(4))
74 if "MAGENTA" in attr:
75 self.screen.attron(curses.color_pair(5))
76 if "RED" in attr:
77 self.screen.attron(curses.color_pair(6))
78 if "WHITE" in attr:
79 self.screen.attron(curses.color_pair(7))
80 if "YELLOW" in attr:
81 self.screen.attron(curses.color_pair(8))
82 if "BOLD" in attr:
83 self.screen.attron(curses.A_BOLD)
84 if "STANDOUT" in attr:
85 self.screen.attron(curses.A_STANDOUT)
86 if "UNDERLINE" in attr:
87 self.screen.attron(curses.A_UNDERLINE)
88
89 out = content[:self.ccols - line_len]
90 self.screen.addstr(out)
91 self.screen.attrset(0)
92 line_len += len(out)
93 l += 1
94 curses_refresh(self.screen)
95
96 def get_input(self):
97 input = getch()
98 if input == UP: input = "up"
99 elif input == DOWN: input = "down"
100 elif input == LEFT: input = "left"
101 elif input == RIGHT: input = "right"
102 elif input == CTRLC: input = "exit"
103 else: input = input.decode("utf-8").lower()
104 return input
105
106 folder_name = "log_1565561768719"
107 divider = " | "
108 title = TITLE
109
110 def loop(self):
111 def tab(string, count=1):
112 return " "*count + string
113 input = None
114 try:
115 while True:
116 self.get_size()
117 screen_width = self.ccols
118
119 self.lines = [
120 [(self.title + " - ", "RESET"), (self.folder_name, "BOLD YELLOW")],
121 "Size: 235 bytes | Timestamp: 1565561768719",
122 "7 Statements | 2 Events | 0 Unsaved Data Trees",
123 pad(margin("STATEMENT 5"), ":", screen_width),
124 "",
125 "[[LOG START]]",
126 "v 7 ITEMS",
127 tab("1565561768752 - INFO - INIT - HELLO"),
128 tab("1565561768752 - INFO - INIT - HELLO"),
129 tab("v 4 ITEMS"),
130 tab("1565561768752 - INFO - INIT - HELLO", 2),
131 tab("1565561768752 - INFO - INIT - HELLO", 2),
132 "",
133 [(tab("1565561768752 - INFO - INIT - HELLO", 2), "BOLD")],
134 "",
135 tab("1565561768752 - INFO - INIT - HELLO", 2),
136 tab("1565561768752 - INFO - INIT - HELLO"),
137 "",
138 str(input),
139 "[[LOG END]",
140 "",
141 "",
142 "",
143 pad(margin(CONTROLS_MESSAGE), ":", screen_width)
144 ]
145 self.redraw()
146
147 input = self.get_input()
148
149 if input == "exit" or input == "q": # exit program on Ctrl + C or `q`
150 break;
151 finally:
152 curses_reset()
153
154def main():
155 options = parseargs(sys.argv[1:])
156
157 display_help = "help" in options
158 display_version = "version" in options
159 is_status = "status" in options
160
161 filter_errors = "errors" in options
162 filter_warnings = "warnings" in options
163 filter_info = "info" in options
164 filter_debug = "debug" in options
165 filter_verbose = "verbose" in options
166 filter_veryverbose = "veryverbose" in options
167
168 filter_after = "after" in options
169 filter_before = "before" in options
170 filter_tag = "tag" in options
171
172 screen_size = term_size()
173 clines = screen_size[0]
174 ccols = screen_size[1]
175
176 if display_help:
177 output(VERSION_SHORT)
178
179 usage = []
180 line = "usage: lognestmonster "
181 x = len(line)
182 width = ccols - x
183 wrapped = wrap(USAGE_MESSAGE, width, "&")
184 for l in wrapped:
185 line += l
186 usage.append(line)
187 line = (" "*x)
188 output_lines(usage)
189
190 output()
191
192 for paragraph in COMMAND_INFO.split("\n\n"):
193 output_lines(wrap(paragraph, ccols))
194
195 output()
196
197 args = []
198
199 div1 = ccols/3
200 div2 = ccols/3*2
201 for arg in ARGUMENT_OPTIONS:
202 arg_lines = []
203 indicators = wrap(", ".join(ARGUMENT_OPTIONS[arg]["indicators"]), div1)
204 description = wrap(ARGUMENT_OPTIONS[arg]["description"], div2)
205 l1 = indicators[0]
206 z = 0
207 for line in description:
208 try:
209 l1 = indicators[z]
210 except:
211 l1 = ""
212 z += 1
213 l = columnize([(div1, l1), (div2, line)], ccols)
214 arg_lines.append(l)
215 args += arg_lines
216
217 output_lines(args)
218 output()
219 output(DESCRIPTION_PYTHON_VERSION)
220 return
221 elif display_version:
222 output(VERSION_MESSAGE)
223 return
224 elif len(sys.argv) == 1 or type(options) is str: # argument error or no args passed
225 exitcode = 0
226 output(VERSION_SHORT)
227 if type(options) is str: # print argument error is exists
228 output(options)
229 exitcode = 1
230 output(HELP_MESSAGE)
231 exit(exitcode)
232
233 positional = sys.argv[-1]
234 if positional is not "-" and os.path.isfile(positional) is not True and os.path.isdir(positional) is not True:
235 output(VERSION_SHORT)
236 output(TEXT_RED + "error:" + RESET + " file unknown '" + positional + "'")
237 output(HELP_MESSAGE)
238 exit(1)
239
240 if positional is "-": positional = "stdin"
241
242 if positional is "stdin":
243 fd = sys.stdin
244 else:
245 try:
246 fd = open(positional, "rb", buffering=8192)
247 except:
248 output(TEXT_RED + "error:" + RESET + " unable to open file")
249 exit(1)
250
251 if not is_status:
252 p = Parser()
253 p.folder_name = positional
254 p.loop()
255 else:
256 r = Reader(fd)
257
258 filter_verbosity_levels = []
259 if filter_errors:
260 filter_verbosity_levels.append(5)
261 if filter_warnings:
262 filter_verbosity_levels.append(4)
263 if filter_info:
264 filter_verbosity_levels.append(0)
265 if filter_debug:
266 filter_verbosity_levels.append(1)
267 if filter_verbose:
268 filter_verbosity_levels.append(2)
269 if filter_veryverbose:
270 filter_verbosity_levels.append(3)
271 if filter_verbosity_levels != []:
272 r.filter_verbosity = filter_verbosity_levels
273 else:
274 r.filter_verbosity = [0, 1, 4, 5]
275
276 if filter_after:
277 try:
278 r.filter_time_start = int(options["after"][0])
279 except:
280 output(VERSION_SHORT)
281 output(TEXT_RED + "error:" + RESET + " expected int for flag --after, got '" + options["after"][0] + "'")
282 output(HELP_MESSAGE)
283 exit(1)
284 if filter_before:
285 try:
286 r.filter_time_end = int(options["before"][0])
287 except:
288 output(VERSION_SHORT)
289 output(TEXT_RED + "error:" + RESET + " expected int for flag --before, got '" + options["before"][0] + "'")
290 output(HELP_MESSAGE)
291 exit(1)
292
293 if filter_tag:
294 r.filter_tag = str(options["tag"][0])
295 if positional is not "stdin": r.size()
296 output("File scan in progress...")
297 s = time.time()
298 def update():
299 if r.statement_count % 100 is 0:
300 output("{0} statements | {1} events | {2} bad bytes | {3}%".format(r.statement_count, r.event_count, r.bad_bytes, round((r.position/r.file_size)*1000)/10), end="\r")
301 r.onupdate(update)
302 r.scan()
303 output()
304 output("Finished in {0} seconds".format(time.time() - s))
305
306 fd.close()
307
308
309if __name__ == "__main__":
310 main()
311