blob: 27ed242bb0defad9bc35bbc99a47b3d8d1498c57 [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
Alex3bc95f62020-03-05 17:00:04 -060028 def __init__(self, area_code, delimiter='-', folder=None):
Alex3ebc5632019-04-18 16:47:18 -050029 self._area_code = area_code
30 self._delimiter = delimiter
31 self._index += 1
32
Alex3bc95f62020-03-05 17:00:04 -060033 # save folder
34 if folder:
35 self._error_logs_folder_name = folder
36
Alexb151fbe2019-04-22 16:53:30 -050037 # init the error log storage folder
38 _folder = os.path.join(pkg_dir, self._error_logs_folder_name)
39 self._conf_filename = os.path.join(
40 _folder,
41 self._conf_filename
42 )
43
Alex7f69a6a2019-05-31 16:53:35 -050044 logger_cli.debug(fu.ensure_folder_exists(_folder))
Alexb151fbe2019-04-22 16:53:30 -050045 if not os.path.exists(self._conf_filename):
46 # put file with init values
47 self.conf = ConfigFile(self._area_code.lower())
48 self.conf.set_value('iteration', self._iteration)
49 self.conf.save_config(filepath=self._conf_filename)
50 logger_cli.debug(
51 "... create new config file '{}'".format(
52 self._conf_filename
53 )
54 )
55 else:
56 # it exists, try to load latest run
57 self.conf = ConfigFile(
58 self._area_code.lower(),
59 filepath=self._conf_filename
60 )
Alex92e07ce2019-05-31 16:00:03 -050061 # check if there is any values there
62 try:
63 self._iteration = self.conf.get_value(
64 'iteration',
65 value_type=int
66 )
67 self._iteration += 1
68 except NoSectionError:
69 self._iteration += 1
70 self.conf.set_value('iteration', self._iteration)
71 self.conf.save_config(filepath=self._conf_filename)
72 logger_cli.debug("... updated config file")
73
Alexb151fbe2019-04-22 16:53:30 -050074 logger_cli.debug(" ... starting iteration {}".format(self._iteration))
75
76 def save_iteration_data(self):
77 # save error log
78 _filename = "-".join([self._area_code.lower(), "errors"])
79 _filename += "." + str(self._iteration)
80 _log_filename = os.path.join(
81 pkg_dir,
82 self._error_logs_folder_name,
83 _filename
84 )
85 fu.write_lines_to_file(_log_filename, self.get_errors(as_list=True))
86 fu.append_line_to_file(_log_filename, "")
87 fu.append_lines_to_file(_log_filename, self.get_summary(as_list=True))
88 logger_cli.debug("... saved errors to '{}'".format(_log_filename))
89
90 # save last iteration number
91 self.conf.set_value('iteration', self._iteration)
92 self.conf.save_config()
93
Alex3ebc5632019-04-18 16:47:18 -050094 def _format_error_code(self, index):
95 _t = "{:02d}".format(self._errors[index]['type'])
96 _i = "{:04d}".format(index)
97 _fmt = self._delimiter.join([self._area_code, _t, _i])
98 return _fmt
99
100 def _format_error(self, index):
101 # error code
102 _code = self._format_error_code(index)
103 # prepare data as string list
104 _d = self._errors[index]['data']
Alex3bc95f62020-03-05 17:00:04 -0600105 _data = [" {}: {}".format(_k, _v) for _k, _v in _d.items()]
Alex3ebc5632019-04-18 16:47:18 -0500106 # format message
Alexb151fbe2019-04-22 16:53:30 -0500107 _msg = "### {}:\n Description: {}\n{}".format(
Alex3ebc5632019-04-18 16:47:18 -0500108 _code,
Alex836fac82019-08-22 13:36:16 -0500109 self.get_error_type_text(self._errors[index]['type']),
Alex3ebc5632019-04-18 16:47:18 -0500110 "\n".join(_data)
111 )
112 return _msg
113
Alex836fac82019-08-22 13:36:16 -0500114 def get_error_type_text(self, err_type):
Alex3ebc5632019-04-18 16:47:18 -0500115 if err_type not in self._types:
116 raise ErrorMappingException(
117 "type code {} not found".format(err_type)
118 )
119 else:
120 return self._types[err_type]
121
122 def get_error_code(self, index):
123 if index in self._errors.keys():
124 return self._format_error(index)
125 else:
126 raise ErrorMappingException(
127 "no error found for index {}".format(index)
128 )
129
130 def add_error_type(self, err_type, message):
131 if err_type in self._types:
132 raise ErrorMappingException(
133 "type code {} reserved for {}".format(
134 err_type,
135 self._types[err_type]
136 )
137 )
138 else:
139 self._types[err_type] = message
140
141 def add_error(self, err_type, **kwargs):
142 # check error type
143 if err_type not in self._types.keys():
144 logger.error(
145 "Error type not listed: '{}'; unknown used".format(err_type)
146 )
147 err_type = 0
148 _err = {
149 "type": err_type,
150 "data": kwargs
151 }
152 self._errors[self._index] = _err
153 self._index += 1
154
155 def get_errors_total(self):
156 return self._index-1
157
158 def get_indices(self):
159 return self._errors.keys()
160
161 def get_error(self, index):
162 if index in self._errors.keys():
163 return self._format_error(index)
164 else:
165 return "Unknown error index of {}".format(index)
166
Alexb151fbe2019-04-22 16:53:30 -0500167 def get_summary(self, print_zeros=True, as_list=False):
Alex3ebc5632019-04-18 16:47:18 -0500168 # create summary with counts per error type
Alexb151fbe2019-04-22 16:53:30 -0500169 _list = "\n{:=^8s}\n{:^8s}\n{:=^8s}".format(
170 "=",
171 "Totals",
172 "="
173 ).splitlines()
174
Alex3ebc5632019-04-18 16:47:18 -0500175 for _type in self._types.keys():
176 _len = len(
Alex3bc95f62020-03-05 17:00:04 -0600177 list(
178 filter(
179 lambda i: self._errors[i]['type'] == _type,
180 self._errors
181 )
Alex3ebc5632019-04-18 16:47:18 -0500182 )
183 )
184 if _len:
185 _num_str = "{:5d}".format(_len)
186 elif print_zeros:
187 _num_str = "{:>5s}".format("-")
188 else:
189 continue
190 _list.append(
191 "{}: {}".format(
192 _num_str,
193 self._types[_type]
194 )
195 )
196
Alexb151fbe2019-04-22 16:53:30 -0500197 _total_errors = self.get_errors_total()
Alex3ebc5632019-04-18 16:47:18 -0500198
Alexb151fbe2019-04-22 16:53:30 -0500199 _list.append('-'*20)
Alex92e07ce2019-05-31 16:00:03 -0500200 _list.append("{:5d} total events found\n".format(_total_errors))
Alexb151fbe2019-04-22 16:53:30 -0500201 if as_list:
202 return _list
203 else:
204 return "\n".join(_list)
Alex3ebc5632019-04-18 16:47:18 -0500205
Alexb151fbe2019-04-22 16:53:30 -0500206 def get_errors(self, as_list=False):
Alex92e07ce2019-05-31 16:00:03 -0500207 _list = ["# Events"]
Alexb151fbe2019-04-22 16:53:30 -0500208 # Detailed errors
209 if self.get_errors_total() > 0:
210 # create list of strings with error messages
Alexbab1efe2019-04-23 18:51:23 -0500211 for _idx in range(1, self._index):
Alexb151fbe2019-04-22 16:53:30 -0500212 _list.append(self._format_error(_idx))
213 _list.append("\n")
214 else:
Alex92e07ce2019-05-31 16:00:03 -0500215 _list.append("-> No events saved")
Alexb151fbe2019-04-22 16:53:30 -0500216
217 if as_list:
218 return _list
219 else:
220 return "\n".join(_list)