##// END OF EJS Templates
logging: log traceback for errors that are known to help debugging.
marcink -
r2449:67bb4316 default
parent child Browse files
Show More
@@ -1,210 +1,215 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2014-2017 RhodeCode GmbH
3 # Copyright (C) 2014-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Custom vcs exceptions module.
22 Custom vcs exceptions module.
23 """
23 """
24
24 import logging
25 import functools
25 import functools
26 import urllib2
26 import urllib2
27
27
28 log = logging.getLogger(__name__)
29
28
30
29 class VCSCommunicationError(Exception):
31 class VCSCommunicationError(Exception):
30 pass
32 pass
31
33
32
34
33 class HttpVCSCommunicationError(VCSCommunicationError):
35 class HttpVCSCommunicationError(VCSCommunicationError):
34 pass
36 pass
35
37
36
38
37 class VCSError(Exception):
39 class VCSError(Exception):
38 pass
40 pass
39
41
40
42
41 class RepositoryError(VCSError):
43 class RepositoryError(VCSError):
42 pass
44 pass
43
45
44
46
45 class RepositoryRequirementError(RepositoryError):
47 class RepositoryRequirementError(RepositoryError):
46 pass
48 pass
47
49
48
50
49 class VCSBackendNotSupportedError(VCSError):
51 class VCSBackendNotSupportedError(VCSError):
50 """
52 """
51 Exception raised when VCSServer does not support requested backend
53 Exception raised when VCSServer does not support requested backend
52 """
54 """
53
55
54
56
55 class EmptyRepositoryError(RepositoryError):
57 class EmptyRepositoryError(RepositoryError):
56 pass
58 pass
57
59
58
60
59 class TagAlreadyExistError(RepositoryError):
61 class TagAlreadyExistError(RepositoryError):
60 pass
62 pass
61
63
62
64
63 class TagDoesNotExistError(RepositoryError):
65 class TagDoesNotExistError(RepositoryError):
64 pass
66 pass
65
67
66
68
67 class BranchAlreadyExistError(RepositoryError):
69 class BranchAlreadyExistError(RepositoryError):
68 pass
70 pass
69
71
70
72
71 class BranchDoesNotExistError(RepositoryError):
73 class BranchDoesNotExistError(RepositoryError):
72 pass
74 pass
73
75
74
76
75 class CommitError(RepositoryError):
77 class CommitError(RepositoryError):
76 """
78 """
77 Exceptions related to an existing commit
79 Exceptions related to an existing commit
78 """
80 """
79
81
80
82
81 class CommitDoesNotExistError(CommitError):
83 class CommitDoesNotExistError(CommitError):
82 pass
84 pass
83
85
84
86
85 class CommittingError(RepositoryError):
87 class CommittingError(RepositoryError):
86 """
88 """
87 Exceptions happening while creating a new commit
89 Exceptions happening while creating a new commit
88 """
90 """
89
91
90
92
91 class NothingChangedError(CommittingError):
93 class NothingChangedError(CommittingError):
92 pass
94 pass
93
95
94
96
95 class NodeError(VCSError):
97 class NodeError(VCSError):
96 pass
98 pass
97
99
98
100
99 class RemovedFileNodeError(NodeError):
101 class RemovedFileNodeError(NodeError):
100 pass
102 pass
101
103
102
104
103 class NodeAlreadyExistsError(CommittingError):
105 class NodeAlreadyExistsError(CommittingError):
104 pass
106 pass
105
107
106
108
107 class NodeAlreadyChangedError(CommittingError):
109 class NodeAlreadyChangedError(CommittingError):
108 pass
110 pass
109
111
110
112
111 class NodeDoesNotExistError(CommittingError):
113 class NodeDoesNotExistError(CommittingError):
112 pass
114 pass
113
115
114
116
115 class NodeNotChangedError(CommittingError):
117 class NodeNotChangedError(CommittingError):
116 pass
118 pass
117
119
118
120
119 class NodeAlreadyAddedError(CommittingError):
121 class NodeAlreadyAddedError(CommittingError):
120 pass
122 pass
121
123
122
124
123 class NodeAlreadyRemovedError(CommittingError):
125 class NodeAlreadyRemovedError(CommittingError):
124 pass
126 pass
125
127
126
128
127 class SubrepoMergeError(RepositoryError):
129 class SubrepoMergeError(RepositoryError):
128 """
130 """
129 This happens if we try to merge a repository which contains subrepos and
131 This happens if we try to merge a repository which contains subrepos and
130 the subrepos cannot be merged. The subrepos are not merged itself but
132 the subrepos cannot be merged. The subrepos are not merged itself but
131 their references in the root repo are merged.
133 their references in the root repo are merged.
132 """
134 """
133
135
134
136
135 class ImproperArchiveTypeError(VCSError):
137 class ImproperArchiveTypeError(VCSError):
136 pass
138 pass
137
139
138
140
139 class CommandError(VCSError):
141 class CommandError(VCSError):
140 pass
142 pass
141
143
142
144
143 class UnhandledException(VCSError):
145 class UnhandledException(VCSError):
144 """
146 """
145 Signals that something unexpected went wrong.
147 Signals that something unexpected went wrong.
146
148
147 This usually means we have a programming error on the side of the VCSServer
149 This usually means we have a programming error on the side of the VCSServer
148 and should inspect the logfile of the VCSServer to find more details.
150 and should inspect the logfile of the VCSServer to find more details.
149 """
151 """
150
152
151
153
152 _EXCEPTION_MAP = {
154 _EXCEPTION_MAP = {
153 'abort': RepositoryError,
155 'abort': RepositoryError,
154 'archive': ImproperArchiveTypeError,
156 'archive': ImproperArchiveTypeError,
155 'error': RepositoryError,
157 'error': RepositoryError,
156 'lookup': CommitDoesNotExistError,
158 'lookup': CommitDoesNotExistError,
157 'repo_locked': RepositoryError,
159 'repo_locked': RepositoryError,
158 'requirement': RepositoryRequirementError,
160 'requirement': RepositoryRequirementError,
159 'unhandled': UnhandledException,
161 'unhandled': UnhandledException,
160 # TODO: johbo: Define our own exception for this and stop abusing
162 # TODO: johbo: Define our own exception for this and stop abusing
161 # urllib's exception class.
163 # urllib's exception class.
162 'url_error': urllib2.URLError,
164 'url_error': urllib2.URLError,
163 'subrepo_merge_error': SubrepoMergeError,
165 'subrepo_merge_error': SubrepoMergeError,
164 }
166 }
165
167
166
168
167 def map_vcs_exceptions(func):
169 def map_vcs_exceptions(func):
168 """
170 """
169 Utility to decorate functions so that plain exceptions are translated.
171 Utility to decorate functions so that plain exceptions are translated.
170
172
171 The translation is based on `exc_map` which maps a `str` indicating
173 The translation is based on `exc_map` which maps a `str` indicating
172 the error type into an exception class representing this error inside
174 the error type into an exception class representing this error inside
173 of the vcs layer.
175 of the vcs layer.
174 """
176 """
175
177
176 @functools.wraps(func)
178 @functools.wraps(func)
177 def wrapper(*args, **kwargs):
179 def wrapper(*args, **kwargs):
178 try:
180 try:
179 return func(*args, **kwargs)
181 return func(*args, **kwargs)
180 except Exception as e:
182 except Exception as e:
181 # The error middleware adds information if it finds
183 # The error middleware adds information if it finds
182 # __traceback_info__ in a frame object. This way the remote
184 # __traceback_info__ in a frame object. This way the remote
183 # traceback information is made available in error reports.
185 # traceback information is made available in error reports.
184 remote_tb = getattr(e, '_vcs_server_traceback', None)
186 remote_tb = getattr(e, '_vcs_server_traceback', None)
185 __traceback_info__ = None
187 __traceback_info__ = None
186 if remote_tb:
188 if remote_tb:
187 if isinstance(remote_tb, basestring):
189 if isinstance(remote_tb, basestring):
188 remote_tb = [remote_tb]
190 remote_tb = [remote_tb]
189 __traceback_info__ = (
191 __traceback_info__ = (
190 'Found VCSServer remote traceback information:\n\n' +
192 'Found VCSServer remote traceback information:\n\n' +
191 '\n'.join(remote_tb))
193 '\n'.join(remote_tb))
192
194
193 # Avoid that remote_tb also appears in the frame
195 # Avoid that remote_tb also appears in the frame
194 del remote_tb
196 del remote_tb
195
197
196 # Special vcs errors had an attribute "_vcs_kind" which is used
198 # Special vcs errors had an attribute "_vcs_kind" which is used
197 # to translate them to the proper exception class in the vcs
199 # to translate them to the proper exception class in the vcs
198 # client layer.
200 # client layer.
199 kind = getattr(e, '_vcs_kind', None)
201 kind = getattr(e, '_vcs_kind', None)
200
202
201 if kind:
203 if kind:
202 if any(e.args):
204 if any(e.args):
203 args = e.args
205 args = e.args
204 else:
206 else:
205 args = [__traceback_info__ or 'unhandledException']
207 args = [__traceback_info__ or 'unhandledException']
206
208 if __traceback_info__ and kind != 'unhandled':
209 # for other than unhandled errors also log the traceback
210 # can be usefull for debugging
211 log.error(__traceback_info__)
207 raise _EXCEPTION_MAP[kind](*args)
212 raise _EXCEPTION_MAP[kind](*args)
208 else:
213 else:
209 raise
214 raise
210 return wrapper
215 return wrapper
General Comments 0
You need to be logged in to leave comments. Login now