blob: 83ae803ab014f93d89a58a6709ec4b80331bd097 [file] [log] [blame]
Alexb151fbe2019-04-22 16:53:30 -05001import os
Alex92e07ce2019-05-31 16:00:03 -05002from configparser import NoSectionError
Alexb151fbe2019-04-22 16:53:30 -05003
4from cfg_checker.common import file_utils as fu
5from cfg_checker.common import logger, logger_cli
6from cfg_checker.common.config_file import ConfigFile
Alex3ebc5632019-04-18 16:47:18 -05007from cfg_checker.common.exception import ErrorMappingException
Alexb151fbe2019-04-22 16:53:30 -05008from cfg_checker.common.settings import pkg_dir
Alex3ebc5632019-04-18 16:47:18 -05009
10
11class ErrorIndex(object):
Alexb151fbe2019-04-22 16:53:30 -050012 # logs folder filenames
13 _error_logs_folder_name = ".cfgerrors"
14 _conf_filename = "conf"
15 # config file object
16 conf = None
17 # iteration counter
18 _iteration = 0
19 # local vars for codes
Alex3ebc5632019-04-18 16:47:18 -050020 _area_code = ""
21 _delimiter = ""
22 _index = 0
23 _errors = {}
24 _types = {
25 0: "Unknown error"
26 }
27
28 def __init__(self, area_code, delimiter='-'):
29 self._area_code = area_code
30 self._delimiter = delimiter
31 self._index += 1
32
Alexb151fbe2019-04-22 16:53:30 -050033 # init the error log storage folder
34 _folder = os.path.join(pkg_dir, self._error_logs_folder_name)
35 self._conf_filename = os.path.join(
36 _folder,
37 self._conf_filename
38 )
39
Alex7f69a6a2019-05-31 16:53:35 -050040 logger_cli.debug(fu.ensure_folder_exists(_folder))
Alexb151fbe2019-04-22 16:53:30 -050041 if not os.path.exists(self._conf_filename):
42 # put file with init values
43 self.conf = ConfigFile(self._area_code.lower())
44 self.conf.set_value('iteration', self._iteration)
45 self.conf.save_config(filepath=self._conf_filename)
46 logger_cli.debug(
47 "... create new config file '{}'".format(
48 self._conf_filename
49 )
50 )
51 else:
52 # it exists, try to load latest run
53 self.conf = ConfigFile(
54 self._area_code.lower(),
55 filepath=self._conf_filename
56 )
Alex92e07ce2019-05-31 16:00:03 -050057 # check if there is any values there
58 try:
59 self._iteration = self.conf.get_value(
60 'iteration',
61 value_type=int
62 )
63 self._iteration += 1
64 except NoSectionError:
65 self._iteration += 1
66 self.conf.set_value('iteration', self._iteration)
67 self.conf.save_config(filepath=self._conf_filename)
68 logger_cli.debug("... updated config file")
69
Alexb151fbe2019-04-22 16:53:30 -050070 logger_cli.debug(" ... starting iteration {}".format(self._iteration))
71
72 def save_iteration_data(self):
73 # save error log
74 _filename = "-".join([self._area_code.lower(), "errors"])
75 _filename += "." + str(self._iteration)
76 _log_filename = os.path.join(
77 pkg_dir,
78 self._error_logs_folder_name,
79 _filename
80 )
81 fu.write_lines_to_file(_log_filename, self.get_errors(as_list=True))
82 fu.append_line_to_file(_log_filename, "")
83 fu.append_lines_to_file(_log_filename, self.get_summary(as_list=True))
84 logger_cli.debug("... saved errors to '{}'".format(_log_filename))
85
86 # save last iteration number
87 self.conf.set_value('iteration', self._iteration)
88 self.conf.save_config()
89
Alex3ebc5632019-04-18 16:47:18 -050090 def _format_error_code(self, index):
91 _t = "{:02d}".format(self._errors[index]['type'])
92 _i = "{:04d}".format(index)
93 _fmt = self._delimiter.join([self._area_code, _t, _i])
94 return _fmt
95
96 def _format_error(self, index):
97 # error code
98 _code = self._format_error_code(index)
99 # prepare data as string list
100 _d = self._errors[index]['data']
Alexb151fbe2019-04-22 16:53:30 -0500101 _data = [" {}: {}".format(_k, _v) for _k, _v in _d.iteritems()]
Alex3ebc5632019-04-18 16:47:18 -0500102 # format message
Alexb151fbe2019-04-22 16:53:30 -0500103 _msg = "### {}:\n Description: {}\n{}".format(
Alex3ebc5632019-04-18 16:47:18 -0500104 _code,
105 self._get_error_type_text(self._errors[index]['type']),
106 "\n".join(_data)
107 )
108 return _msg
109
110 def _get_error_type_text(self, err_type):
111 if err_type not in self._types:
112 raise ErrorMappingException(
113 "type code {} not found".format(err_type)
114 )
115 else:
116 return self._types[err_type]
117
118 def get_error_code(self, index):
119 if index in self._errors.keys():
120 return self._format_error(index)
121 else:
122 raise ErrorMappingException(
123 "no error found for index {}".format(index)
124 )
125
126 def add_error_type(self, err_type, message):
127 if err_type in self._types:
128 raise ErrorMappingException(
129 "type code {} reserved for {}".format(
130 err_type,
131 self._types[err_type]
132 )
133 )
134 else:
135 self._types[err_type] = message
136
137 def add_error(self, err_type, **kwargs):
138 # check error type
139 if err_type not in self._types.keys():
140 logger.error(
141 "Error type not listed: '{}'; unknown used".format(err_type)
142 )
143 err_type = 0
144 _err = {
145 "type": err_type,
146 "data": kwargs
147 }
148 self._errors[self._index] = _err
149 self._index += 1
150
151 def get_errors_total(self):
152 return self._index-1
153
154 def get_indices(self):
155 return self._errors.keys()
156
157 def get_error(self, index):
158 if index in self._errors.keys():
159 return self._format_error(index)
160 else:
161 return "Unknown error index of {}".format(index)
162
Alexb151fbe2019-04-22 16:53:30 -0500163 def get_summary(self, print_zeros=True, as_list=False):
Alex3ebc5632019-04-18 16:47:18 -0500164 # create summary with counts per error type
Alexb151fbe2019-04-22 16:53:30 -0500165 _list = "\n{:=^8s}\n{:^8s}\n{:=^8s}".format(
166 "=",
167 "Totals",
168 "="
169 ).splitlines()
170
Alex3ebc5632019-04-18 16:47:18 -0500171 for _type in self._types.keys():
172 _len = len(
173 filter(
174 lambda i: self._errors[i]['type'] == _type,
175 self._errors
176 )
177 )
178 if _len:
179 _num_str = "{:5d}".format(_len)
180 elif print_zeros:
181 _num_str = "{:>5s}".format("-")
182 else:
183 continue
184 _list.append(
185 "{}: {}".format(
186 _num_str,
187 self._types[_type]
188 )
189 )
190
Alexb151fbe2019-04-22 16:53:30 -0500191 _total_errors = self.get_errors_total()
Alex3ebc5632019-04-18 16:47:18 -0500192
Alexb151fbe2019-04-22 16:53:30 -0500193 _list.append('-'*20)
Alex92e07ce2019-05-31 16:00:03 -0500194 _list.append("{:5d} total events found\n".format(_total_errors))
Alexb151fbe2019-04-22 16:53:30 -0500195 if as_list:
196 return _list
197 else:
198 return "\n".join(_list)
Alex3ebc5632019-04-18 16:47:18 -0500199
Alexb151fbe2019-04-22 16:53:30 -0500200 def get_errors(self, as_list=False):
Alex92e07ce2019-05-31 16:00:03 -0500201 _list = ["# Events"]
Alexb151fbe2019-04-22 16:53:30 -0500202 # Detailed errors
203 if self.get_errors_total() > 0:
204 # create list of strings with error messages
Alexbab1efe2019-04-23 18:51:23 -0500205 for _idx in range(1, self._index):
Alexb151fbe2019-04-22 16:53:30 -0500206 _list.append(self._format_error(_idx))
207 _list.append("\n")
208 else:
Alex92e07ce2019-05-31 16:00:03 -0500209 _list.append("-> No events saved")
Alexb151fbe2019-04-22 16:53:30 -0500210
211 if as_list:
212 return _list
213 else:
214 return "\n".join(_list)