Integrating latest 47acbe8

This commit is contained in:
alexpete
2021-03-25 13:57:57 -07:00
parent 448c549698
commit 75dc720198
10312 changed files with 2711566 additions and 671451 deletions
+100
View File
@@ -0,0 +1,100 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
from EventLogger.Utils import EventBoundary, EventHeader, EventNameHash, LogHeader, Prolog, PrologId
def size_align_up(size, align):
return (size + (align - 1)) & ~(align - 1)
class Reader(object):
ReadStatus_Success = 0
ReadStatus_InsufficientFileSize = -1
ReadStatus_InvalidFormat = -2
ReadStatus_NoEvents = -3
def __init__(self):
self.log_header = LogHeader()
self.current_event = EventHeader()
self.current_thread_id = None
self.buffer = None
self.buffer_size = 0
self.buffer_pos = 0
def read_log_file(self, file_path):
with open(file_path, mode='rb') as log_file:
self.buffer = log_file.read()
self.buffer_size = len(self.buffer)
if self.buffer_size < LogHeader.size():
return Reader.ReadStatus_InsufficientFileSize
self.log_header.unpack(self.buffer)
self.buffer_pos = LogHeader.size()
if self.log_header.get_format() not in LogHeader.accepted_formats():
return Reader.ReadStatus_InvalidFormat
if self.buffer_pos + EventHeader.size() > self.buffer_size:
return Reader.ReadStatus_NoEvents
self.current_event.unpack(self._get_next(EventHeader.size()))
self._update_thread_id()
return Reader.ReadStatus_Success
def get_log_header(self):
return self.log_header
def get_thread_id(self):
return self.current_thread_id
def get_event_name(self):
return EventNameHash(self.current_event.event_id)
def get_event_size(self):
return self.current_event.size
def get_event_flags(self):
return self.current_event.flags
def get_event_data(self):
start = self.buffer_pos + EventHeader.size()
return self._get_next(self.get_event_size(), override_start=start)
def get_event_string(self):
string_data = self.get_event_data()
return string_data.decode('utf-8')
def next(self):
real_size = EventHeader.size() + self.get_event_size()
self.buffer_pos += size_align_up(real_size, EventBoundary)
if self.buffer_pos < self.buffer_size:
self.current_event.unpack(self._get_next(EventHeader.size()))
self._update_thread_id()
return True
return False
def _get_next(self, size, override_start=None):
start = override_start or self.buffer_pos
end = start + size
return self.buffer[start:end]
def _update_thread_id(self):
if self.get_event_name() == PrologId:
prolog = Prolog()
prolog.unpack(self._get_next(Prolog.size()))
self.current_thread_id = prolog.thread_id
+121
View File
@@ -0,0 +1,121 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
import struct
import sys
# Simple hash structure based on DJB2a
class EventNameHash(object):
def __init__(self, name):
if isinstance(name, int):
self.hash = name
else:
value = 5381
for i in range(len(name)):
value = ((value << 5) + value) ^ ord(name[i])
self.hash = value & 0xFFFFFFFF
def __hash__(self):
return self.hash
def __eq__(self, rhs):
if isinstance(rhs, EventNameHash):
return self.hash == rhs.hash
else:
return self.hash == rhs
PrologId = EventNameHash("Prolog")
EventBoundary = 8
class LogStructBase(object):
def _unpack(self, member_info, data):
pos = 0
for (member, data_format, data_size) in member_info:
pos_end = pos + data_size
unpacked_value = struct.unpack(data_format, data[pos:pos_end])
setattr(self, member, unpacked_value[0])
pos = pos_end
class LogHeader(LogStructBase):
@staticmethod
def size():
return 16
@staticmethod
def accepted_formats():
return ['AZEL']
def __init__(self):
self.four_cc = None
self.major_version = None
self.minor_version = None
self.user_version = None
def unpack(self, data):
member_info = [
('four_cc', '@4s', 4),
('major_version', '@I', 4),
('minor_version', '@I', 4),
('user_version', '@I', 4),
]
self._unpack(member_info, data)
def get_format(self):
return self.four_cc.decode('utf-8')
def get_version(self):
return f'{self.major_version}.{self.minor_version} ({self.user_version})'
class EventHeader(LogStructBase):
@staticmethod
def size():
return 8
def __init__(self):
self.event_id = None
self.size = None
self.flags = None
def unpack(self, data):
member_info = [
('event_id', '@I', 4),
('size', '@H', 2),
('flags', '@H', 2),
]
self._unpack(member_info, data)
class Prolog(EventHeader):
@staticmethod
def size():
return 16
def __init__(self):
super().__init__()
self.thread_id = None
def unpack(self, data):
member_info = [
('event_id', '@I', 4),
('size', '@H', 2),
('flags', '@H', 2),
('thread_id', '@Q', 8)
]
self._unpack(member_info, data)
@@ -0,0 +1,10 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
+68
View File
@@ -0,0 +1,68 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
from EventLogger.Reader import Reader
from EventLogger.Utils import EventNameHash, PrologId
import argparse
import os
import sys
AssertId = EventNameHash("Assert")
ErrorId = EventNameHash("Error")
MessageId = EventNameHash("Message")
PrintfId = EventNameHash("Printf")
WarningId = EventNameHash("Warning")
def main(args):
parser = argparse.ArgumentParser(description='Simple Event Logger Printer')
parser.add_argument('file', type=str, help='Path log file')
parsed_args = parser.parse_args(args)
log_file = parsed_args.file
if not os.path.exists(log_file):
print('[ERROR] Invalid file path supplied')
exit(1)
log_reader = Reader()
status = log_reader.read_log_file(log_file)
if status == Reader.ReadStatus_InsufficientFileSize:
print('File size too small to contain Event Logger information')
return
elif status == Reader.ReadStatus_InvalidFormat:
print('Invalid Event Logger format detected')
return
log_header = log_reader.get_log_header()
print(f'Log File: {log_file}')
print(f'Format: {log_header.get_format()}')
print(f'Version: {log_header.get_version()}')
has_event = (status == Reader.ReadStatus_Success)
while has_event:
event_id = log_reader.get_event_name()
if event_id == PrologId:
print(f'Thread: {log_reader.get_thread_id()}')
elif event_id in (AssertId, ErrorId, WarningId, PrintfId, MessageId):
print(f'> {log_reader.get_event_string()}')
else:
print(f'Event ID {event_id}, Size {log_reader.get_event_size()}')
has_event = log_reader.next()
if __name__ == '__main__':
main(sys.argv[1:])
+157
View File
@@ -0,0 +1,157 @@
#
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
# its licensors.
#
# For complete copyright and license terms please see the LICENSE at the root of this
# distribution (the "License"). All use of this software is governed by the License,
# or, if provided, by the license below or the license accompanying this file. Do not
# remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
from EventLogger.Reader import Reader
from EventLogger.Utils import EventNameHash, PrologId
from tkinter import filedialog
from tkinter import ttk
from tkinter import *
import tkinter
import struct
AssertId = EventNameHash("Assert")
ErrorId = EventNameHash("Error")
MessageId = EventNameHash("Message")
PrintfId = EventNameHash("Printf")
WarningId = EventNameHash("Warning")
class TraceViewer(object):
def __init__(self):
self._tab_content = {}
self._window = window = tkinter.Tk()
window.title('Trace Viewer')
window.minsize(640, 480)
# file menu
self._file_menu = file_menu = Menubutton(window, text='File')
file_menu.menu = Menu(file_menu, tearoff=0)
file_menu['menu'] = file_menu.menu
file_menu.pack(side=TOP, anchor=W)
file_menu.menu.add_command(label='Open...', command=self._open_file)
file_menu.menu.add_command(label='Exit', command=window.quit)
# main content
self._main_view = main_view = ttk.Notebook(window)
main_view.pack(fill=BOTH, expand=1)
# setup a debug tab for internal logging
self._add_new_tab('Debug')
def run(self):
self._window.mainloop()
def _reset(self):
for tab in self._main_view.winfo_children():
tab.destroy()
self._add_new_tab('Debug')
def _add_new_tab(self, name):
tab = ttk.Frame(self._main_view)
vscrollbar = Scrollbar(tab)
hscrollbar = Scrollbar(tab, orient='horizontal')
text_box = Text(tab, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap=NONE)
text_box.tag_config('Assert', foreground='red3', background='gray80')
text_box.tag_config('Error', foreground='red2')
text_box.tag_config('Warning', foreground='SteelBlue3')
vscrollbar.config(command=text_box.yview)
hscrollbar.config(command=text_box.xview)
vscrollbar.pack(side=RIGHT, fill=Y)
hscrollbar.pack(side=BOTTOM, fill=X)
text_box.pack(fill=BOTH, expand=1)
self._main_view.add(tab, text=name)
self._tab_content[name] = text_box
self._active_content = text_box
def _append_debug_message(self, message):
debug_content = self._tab_content['Debug']
debug_content.insert(END, f'{message}\n')
def _append_current_message(self, message):
if self._active_content:
self._active_content.insert(END, f'{message}\n')
def _append_current_tagged_message(self, message, tag):
if self._active_content:
start = self._active_content.index('insert linestart')
self._active_content.insert(END, f'{message}\n')
self._active_content.tag_add(tag, start, 'insert lineend')
def _open_file(self):
log_file_types = [
('log files','*.azel'),
('log files','*.bin'),
('all files','*.*')
]
log_file = filedialog.askopenfilename(initialdir='../../', title='Select log file', filetypes=log_file_types)
if not log_file:
self._append_debug_message('Invalid file')
return
self._reset()
log_reader = Reader()
status = log_reader.read_log_file(log_file)
if status == Reader.ReadStatus_InsufficientFileSize:
self._append_debug_message('File size too small to contain Event Logger information')
return
elif status == Reader.ReadStatus_InvalidFormat:
self._append_debug_message('Invalid Event Logger format detected')
return
log_header = log_reader.get_log_header()
self._append_debug_message(f'Log File: {log_file}')
self._append_debug_message(f'Format: {log_header.get_format()}')
self._append_debug_message(f'Version: {log_header.get_version()}')
tagged_messages = { AssertId : 'Assert', ErrorId : 'Error', WarningId : 'Warning' }
has_event = (status == Reader.ReadStatus_Success)
while has_event:
event_id = log_reader.get_event_name()
if event_id == PrologId:
tab_name = f'Thread {log_reader.get_thread_id()}'
if tab_name in self._tab_content:
self._active_content = self._tab_content[tab_name]
else:
self._add_new_tab(tab_name)
elif event_id in tagged_messages:
self._append_current_tagged_message(log_reader.get_event_string(), tagged_messages[event_id])
elif event_id in (PrintfId, MessageId):
self._append_current_message(log_reader.get_event_string())
else:
self._append_current_message(f'Event ID {event_id}, Size {log_reader.get_event_size()}')
has_event = log_reader.next()
def main():
trace_viewer = TraceViewer()
trace_viewer.run()
if __name__ == '__main__':
main()