Skip to content

Commit 1975e12

Browse files
committed
make exceptions more useful
1 parent 80d4e00 commit 1975e12

File tree

4 files changed

+104
-53
lines changed

4 files changed

+104
-53
lines changed

testgres/consts.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
LOGS_DIR = "logs"
66

77
RECOVERY_CONF_FILE = "recovery.conf"
8+
PG_AUTO_CONF_FILE = "postgresql.auto.conf"
89
PG_CONF_FILE = "postgresql.conf"
910
HBA_CONF_FILE = "pg_hba.conf"
1011

testgres/exceptions.py

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,95 @@
11
# coding: utf-8
22

3+
import six
34

4-
class TestgresException(Exception):
5-
"""
6-
Base exception
7-
"""
85

9-
pass
6+
@six.python_2_unicode_compatible
7+
class TestgresException(Exception):
8+
def __str__(self):
9+
s = super(TestgresException, self).__str__()
10+
return six.text_type(s)
1011

1112

1213
class ExecUtilException(TestgresException):
13-
"""
14-
Stores exit code
15-
"""
16-
17-
def __init__(self, message, exit_code=0):
14+
def __init__(self,
15+
message=None,
16+
command=None,
17+
exit_code=0,
18+
out=None):
1819
super(ExecUtilException, self).__init__(message)
20+
21+
self.message = message
22+
self.command = command
1923
self.exit_code = exit_code
24+
self.out = out
2025

26+
def __str__(self):
27+
msg = []
2128

22-
class ClusterTestgresException(TestgresException):
23-
pass
29+
if self.message:
30+
msg.append(self.message)
31+
32+
if self.command:
33+
msg.append('Command: {}'.format(self.command))
34+
35+
if self.exit_code:
36+
msg.append('Exit code: {}'.format(self.exit_code))
37+
38+
if self.out:
39+
msg.append('----\n{}'.format(self.out))
40+
41+
return six.text_type('\n').join(msg)
2442

2543

2644
class QueryException(TestgresException):
45+
def __init__(self, message=None, query=None):
46+
super(QueryException, self).__init__(message)
47+
48+
self.message = message
49+
self.query = query
50+
51+
def __str__(self):
52+
msg = []
53+
54+
if self.message:
55+
msg.append(self.message)
56+
57+
if self.query:
58+
msg.append('Query: {}'.format(self.query))
59+
60+
return six.text_type('\n').join(msg)
61+
62+
63+
class TimeoutException(QueryException):
2764
pass
2865

2966

30-
class TimeoutException(TestgresException):
67+
class CatchUpException(QueryException):
3168
pass
3269

3370

3471
class StartNodeException(TestgresException):
35-
pass
72+
def __init__(self, message=None, files=None):
73+
super(StartNodeException, self).__init__(message)
3674

75+
self.message = message
76+
self.files = files
3777

38-
class InitNodeException(TestgresException):
39-
pass
78+
def __str__(self):
79+
msg = []
4080

81+
if self.message:
82+
msg.append(self.message)
4183

42-
class BackupException(TestgresException):
84+
for key, value in six.iteritems(self.files or {}):
85+
msg.append('{}\n----\n{}\n'.format(key, value))
86+
87+
return six.text_type('\n').join(msg)
88+
89+
90+
class InitNodeException(TestgresException):
4391
pass
4492

4593

46-
class CatchUpException(TestgresException):
94+
class BackupException(TestgresException):
4795
pass

testgres/node.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
DATA_DIR, \
2525
LOGS_DIR, \
2626
PG_CONF_FILE, \
27+
PG_AUTO_CONF_FILE, \
2728
HBA_CONF_FILE, \
2829
RECOVERY_CONF_FILE, \
2930
PG_LOG_FILE, \
@@ -215,22 +216,18 @@ def _maybe_stop_logger(self):
215216
if self._logger:
216217
self._logger.stop()
217218

218-
def _format_verbose_error(self, message=None):
219-
# list of important files + N of last lines
219+
def _collect_special_files(self):
220+
result = {}
221+
222+
# list of important files + last N lines
220223
files = [
221224
(os.path.join(self.data_dir, PG_CONF_FILE), 0),
222-
(os.path.join(self.data_dir, HBA_CONF_FILE), 0),
225+
(os.path.join(self.data_dir, PG_AUTO_CONF_FILE), 0),
223226
(os.path.join(self.data_dir, RECOVERY_CONF_FILE), 0),
227+
(os.path.join(self.data_dir, HBA_CONF_FILE), 0),
224228
(self.pg_log_name, TestgresConfig.error_log_lines)
225229
]
226230

227-
error_text = ""
228-
229-
# append message if asked to
230-
if message:
231-
error_text += message
232-
error_text += '\n' * 2
233-
234231
for f, num_lines in files:
235232
# skip missing files
236233
if not os.path.exists(f):
@@ -244,10 +241,10 @@ def _format_verbose_error(self, message=None):
244241
# read whole file
245242
lines = _f.read().decode('utf-8')
246243

247-
# append contents
248-
error_text += u"{}:\n----\n{}\n".format(f, lines)
244+
# fill dict
245+
result[f] = lines
249246

250-
return error_text
247+
return result
251248

252249
def init(self,
253250
fsync=False,
@@ -429,7 +426,8 @@ def get_pid(self):
429426
"""
430427

431428
if self.status():
432-
with io.open(os.path.join(self.data_dir, 'postmaster.pid')) as f:
429+
pid_file = os.path.join(self.data_dir, 'postmaster.pid')
430+
with io.open(pid_file) as f:
433431
return int(f.readline())
434432

435433
# for clarity
@@ -478,8 +476,9 @@ def start(self, params=[]):
478476
try:
479477
execute_utility(_params, self.utils_log_name)
480478
except ExecUtilException as e:
481-
msg = self._format_verbose_error('Cannot start node')
482-
raise_from(StartNodeException(msg), e)
479+
msg = 'Cannot start node'
480+
files = self._collect_special_files()
481+
raise_from(StartNodeException(msg, files), e)
483482

484483
self._maybe_start_logger()
485484

@@ -533,8 +532,9 @@ def restart(self, params=[]):
533532
try:
534533
execute_utility(_params, self.utils_log_name)
535534
except ExecUtilException as e:
536-
msg = self._format_verbose_error('Cannot restart node')
537-
raise_from(StartNodeException(msg), e)
535+
msg = 'Cannot restart node'
536+
files = self._collect_special_files()
537+
raise_from(StartNodeException(msg, files), e)
538538

539539
self._maybe_start_logger()
540540

@@ -695,7 +695,7 @@ def safe_psql(self,
695695
username=username,
696696
input=input)
697697
if ret:
698-
raise QueryException((err or b'').decode('utf-8'))
698+
raise QueryException((err or b'').decode('utf-8'), query)
699699

700700
return out
701701

@@ -793,13 +793,13 @@ def poll_query_until(self,
793793
return # done
794794

795795
if res is None:
796-
raise QueryException('Query returned None')
796+
raise QueryException('Query returned None', query)
797797

798798
if len(res) == 0:
799-
raise QueryException('Query returned 0 rows')
799+
raise QueryException('Query returned 0 rows', query)
800800

801801
if len(res[0]) == 0:
802-
raise QueryException('Query returned 0 columns')
802+
raise QueryException('Query returned 0 columns', query)
803803

804804
if res[0][0] == expected:
805805
return # done
@@ -916,7 +916,7 @@ def catchup(self, dbname=None, username=None):
916916
username=username,
917917
max_attempts=0) # infinite
918918
except Exception as e:
919-
raise_from(CatchUpException('Failed to catch up'), e)
919+
raise_from(CatchUpException("Failed to catch up", poll_lsn), e)
920920

921921
def pgbench(self,
922922
dbname=None,

testgres/utils.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,29 +90,31 @@ def execute_utility(args, logfile):
9090
out, _ = process.communicate()
9191
out = '' if not out else out.decode('utf-8')
9292

93+
# format command
94+
command = u' '.join(args)
95+
9396
# write new log entry if possible
9497
try:
9598
with io.open(logfile, 'a') as file_out:
96-
# write util's name and args
97-
file_out.write(u' '.join(args))
99+
file_out.write(command)
98100

99-
# write output
100101
if out:
102+
# comment-out lines
103+
lines = ('# ' + l for l in out.splitlines())
101104
file_out.write(u'\n')
102-
file_out.write(out)
105+
file_out.writelines(lines)
103106

104-
# finally, a separator
105107
file_out.write(u'\n')
106108
except IOError:
107109
pass
108110

109-
# format exception, if needed
110-
error_code = process.returncode
111-
if error_code:
112-
error_text = (u"{} failed with exit code {}\n"
113-
u"log:\n----\n{}\n").format(args[0], error_code, out)
114-
115-
raise ExecUtilException(error_text, error_code)
111+
exit_code = process.returncode
112+
if exit_code:
113+
message = 'Failed to execute utility'
114+
raise ExecUtilException(message=message,
115+
command=command,
116+
exit_code=exit_code,
117+
out=out)
116118

117119
return out
118120

0 commit comments

Comments
 (0)