Index

lognestmonster / d582544

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

Latest Commit

{#}TimeHashSubjectAuthor#(+)(-)GPG?
9608 Sep 2019 17:02d582544update parsingJosh Stockin142N

Blob @ lognestmonster / parser / parse.py

application/x-python8137 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 output_exit(error=None):
155 exitcode = 0
156 output(VERSION_SHORT)
157 if error is not None: # print argument error is exists
158 output(TEXT_RED + "error: " + RESET + error)
159 exitcode = 1
160 output(HELP_MESSAGE)
161 exit(exitcode)
162
163def main():
164 options = parseargs(sys.argv[1:])
165
166 display_help = "help" in options
167 display_version = "version" in options
168 is_status = "status" in options
169
170 filter_errors = "errors" in options
171 filter_warnings = "warnings" in options
172 filter_info = "info" in options
173 filter_debug = "debug" in options
174 filter_verbose = "verbose" in options
175 filter_veryverbose = "veryverbose" in options
176
177 filter_after = "after" in options
178 filter_before = "before" in options
179 filter_tag = "tag" in options
180
181 screen_size = term_size()
182 clines = screen_size[0]
183 ccols = screen_size[1]
184
185 if display_help:
186 output(VERSION_SHORT)
187
188 output("usage: lognestmonster " + USAGE_MESSAGE)
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 = int(ccols/3)
200 div2 = int(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 if type(options) is str: # print argument error is exists
226 output_exit(options)
227 else:
228 output_exit()
229
230 positional = sys.argv[-1]
231 if positional is not "-" and os.path.isfile(positional) is not True and os.path.isdir(positional) is not True:
232 output_exit("file unknown '" + positional + "'")
233
234 if positional is "-": positional = "stdin"
235
236 if positional is "stdin":
237 fd = sys.stdin
238 else:
239 try:
240 fd = open(positional, "rb", buffering=8192)
241 except:
242 output_exit("unable to open file '" + positional + "'")
243
244 if not is_status:
245 p = Parser()
246 p.folder_name = positional
247 p.loop()
248 else:
249 r = Reader(fd)
250
251 filter_verbosity_levels = []
252 if filter_errors:
253 filter_verbosity_levels.append(5)
254 if filter_warnings:
255 filter_verbosity_levels.append(4)
256 if filter_info:
257 filter_verbosity_levels.append(0)
258 if filter_debug:
259 filter_verbosity_levels.append(1)
260 if filter_verbose:
261 filter_verbosity_levels.append(2)
262 if filter_veryverbose:
263 filter_verbosity_levels.append(3)
264 if filter_verbosity_levels != []:
265 r.filter_verbosity = filter_verbosity_levels
266 r.filters = True
267 else:
268 r.filter_verbosity = [0, 1, 2, 3, 4, 5]
269
270 if filter_after:
271 try:
272 r.filter_time_start = int(options["after"][0])
273 r.filters = True
274 except:
275 output_exit("expected int for flag --after, got '" + options["after"][0] + "'")
276 if filter_before:
277 try:
278 r.filter_time_end = int(options["before"][0])
279 r.filters = True
280 except:
281 output_exit("expected int for flag --before, got '" + options["before"][0] + "'")
282
283 if filter_tag:
284 r.filter_tag = str(options["tag"][0])
285 r.filters = True
286 if positional is not "stdin": r.size()
287 else: r.seekable = False
288 output("File scan in progress...")
289 s = time.time()
290 def update():
291 if r.statement_count % 1000 == 0:
292 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")
293 r.onupdate(update)
294 r.scan()
295 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))
296 elapsed = time.time() - s
297 if elapsed > 1:
298 output("Finished in {0} seconds".format(elapsed))
299
300 fd.close()
301
302
303if __name__ == "__main__":
304 main()
305