blob: eaaa1ebed62f01de9bb997a953d6b14bcffa2f52 [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
40 if not os.path.exists(_folder):
41 # it is not exists, create it
42 os.mkdir(_folder)
43 logger_cli.debug(
44 "... error logs folder '{}' created".format(_folder)
45 )
46 else:
47 logger_cli.debug(
48 "... error logs folder is at '{}'".format(_folder)
49 )
50 if not os.path.exists(self._conf_filename):
51 # put file with init values
52 self.conf = ConfigFile(self._area_code.lower())
53 self.conf.set_value('iteration', self._iteration)
54 self.conf.save_config(filepath=self._conf_filename)
55 logger_cli.debug(
56 "... create new config file '{}'".format(
57 self._conf_filename
58 )
59 )
60 else:
61 # it exists, try to load latest run
62 self.conf = ConfigFile(
63 self._area_code.lower(),
64 filepath=self._conf_filename
65 )
Alex92e07ce2019-05-31 16:00:03 -050066 # check if there is any values there
67 try:
68 self._iteration = self.conf.get_value(
69 'iteration',
70 value_type=int
71 )
72 self._iteration += 1
73 except NoSectionError:
74 self._iteration += 1
75 self.conf.set_value('iteration', self._iteration)
76 self.conf.save_config(filepath=self._conf_filename)
77 logger_cli.debug("... updated config file")
78
Alexb151fbe2019-04-22 16:53:30 -050079 logger_cli.debug(" ... starting iteration {}".format(self._iteration))
80
81 def save_iteration_data(self):
82 # save error log
83 _filename = "-".join([self._area_code.lower(), "errors"])
84 _filename += "." + str(self._iteration)
85 _log_filename = os.path.join(
86 pkg_dir,
87 self._error_logs_folder_name,
88 _filename
89 )
90 fu.write_lines_to_file(_log_filename, self.get_errors(as_list=True))
91 fu.append_line_to_file(_log_filename, "")
92 fu.append_lines_to_file(_log_filename, self.get_summary(as_list=True))
93 logger_cli.debug("... saved errors to '{}'".format(_log_filename))
94
95 # save last iteration number
96 self.conf.set_value('iteration', self._iteration)
97 self.conf.save_config()
98
Alex3ebc5632019-04-18 16:47:18 -050099 def _format_error_code(self, index):
100 _t = "{:02d}".format(self._errors[index]['type'])
101 _i = "{:04d}".format(index)
102 _fmt = self._delimiter.join([self._area_code, _t, _i])
103 return _fmt
104
105 def _format_error(self, index):
106 # error code
107 _code = self._format_error_code(index)
108 # prepare data as string list
109 _d = self._errors[index]['data']
Alexb151fbe2019-04-22 16:53:30 -0500110 _data = [" {}: {}".format(_k, _v) for _k, _v in _d.iteritems()]
Alex3ebc5632019-04-18 16:47:18 -0500111 # format message
Alexb151fbe2019-04-22 16:53:30 -0500112 _msg = "### {}:\n Description: {}\n{}".format(
Alex3ebc5632019-04-18 16:47:18 -0500113 _code,
114 self._get_error_type_text(self._errors[index]['type']),
115 "\n".join(_data)
116 )
117 return _msg
118
119 def _get_error_type_text(self, err_type):
120 if err_type not in self._types:
121 raise ErrorMappingException(
122 "type code {} not found".format(err_type)
123 )
124 else:
125 return self._types[err_type]
126
127 def get_error_code(self, index):
128 if index in self._errors.keys():
129 return self._format_error(index)
130 else:
131 raise ErrorMappingException(
132 "no error found for index {}".format(index)
133 )
134
135 def add_error_type(self, err_type, message):
136 if err_type in self._types:
137 raise ErrorMappingException(
138 "type code {} reserved for {}".format(
139 err_type,
140 self._types[err_type]
141 )
142 )
143 else:
144 self._types[err_type] = message
145
146 def add_error(self, err_type, **kwargs):
147 # check error type
148 if err_type not in self._types.keys():
149 logger.error(
150 "Error type not listed: '{}'; unknown used".format(err_type)
151 )
152 err_type = 0
153 _err = {
154 "type": err_type,
155 "data": kwargs
156 }
157 self._errors[self._index] = _err
158 self._index += 1
159
160 def get_errors_total(self):
161 return self._index-1
162
163 def get_indices(self):
164 return self._errors.keys()
165
166 def get_error(self, index):
167 if index in self._errors.keys():
168 return self._format_error(index)
169 else:
170 return "Unknown error index of {}".format(index)
171
Alexb151fbe2019-04-22 16:53:30 -0500172 def get_summary(self, print_zeros=True, as_list=False):
Alex3ebc5632019-04-18 16:47:18 -0500173 # create summary with counts per error type
Alexb151fbe2019-04-22 16:53:30 -0500174 _list = "\n{:=^8s}\n{:^8s}\n{:=^8s}".format(
175 "=",
176 "Totals",
177 "="
178 ).splitlines()
179
Alex3ebc5632019-04-18 16:47:18 -0500180 for _type in self._types.keys():
181 _len = len(
182 filter(
183 lambda i: self._errors[i]['type'] == _type,
184 self._errors
185 )
186 )
187 if _len:
188 _num_str = "{:5d}".format(_len)
189 elif print_zeros:
190 _num_str = "{:>5s}".format("-")
191 else:
192 continue
193 _list.append(
194 "{}: {}".format(
195 _num_str,
196 self._types[_type]
197 )
198 )
199
Alexb151fbe2019-04-22 16:53:30 -0500200 _total_errors = self.get_errors_total()
Alex3ebc5632019-04-18 16:47:18 -0500201
Alexb151fbe2019-04-22 16:53:30 -0500202 _list.append('-'*20)
Alex92e07ce2019-05-31 16:00:03 -0500203 _list.append("{:5d} total events found\n".format(_total_errors))
Alexb151fbe2019-04-22 16:53:30 -0500204 if as_list:
205 return _list
206 else:
207 return "\n".join(_list)
Alex3ebc5632019-04-18 16:47:18 -0500208
Alexb151fbe2019-04-22 16:53:30 -0500209 def get_errors(self, as_list=False):
Alex92e07ce2019-05-31 16:00:03 -0500210 _list = ["# Events"]
Alexb151fbe2019-04-22 16:53:30 -0500211 # Detailed errors
212 if self.get_errors_total() > 0:
213 # create list of strings with error messages
Alexbab1efe2019-04-23 18:51:23 -0500214 for _idx in range(1, self._index):
Alexb151fbe2019-04-22 16:53:30 -0500215 _list.append(self._format_error(_idx))
216 _list.append("\n")
217 else:
Alex92e07ce2019-05-31 16:00:03 -0500218 _list.append("-> No events saved")
Alexb151fbe2019-04-22 16:53:30 -0500219
220 if as_list:
221 return _list
222 else:
223 return "\n".join(_list)