##// END OF EJS Templates
blackbox: use absolute_import
Gregory Szorc -
r28090:8113c88b default
parent child Browse files
Show More
@@ -1,165 +1,172 b''
1 1 # blackbox.py - log repository events to a file for post-mortem debugging
2 2 #
3 3 # Copyright 2010 Nicolas Dumazet
4 4 # Copyright 2013 Facebook, Inc.
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 """log repository events to a blackbox for debugging
10 10
11 11 Logs event information to .hg/blackbox.log to help debug and diagnose problems.
12 12 The events that get logged can be configured via the blackbox.track config key.
13 13 Examples::
14 14
15 15 [blackbox]
16 16 track = *
17 17
18 18 [blackbox]
19 19 track = command, commandfinish, commandexception, exthook, pythonhook
20 20
21 21 [blackbox]
22 22 track = incoming
23 23
24 24 [blackbox]
25 25 # limit the size of a log file
26 26 maxsize = 1.5 MB
27 27 # rotate up to N log files when the current one gets too big
28 28 maxfiles = 3
29 29
30 30 """
31 31
32 from mercurial import util, cmdutil
32 from __future__ import absolute_import
33
34 import errno
35 import re
36
33 37 from mercurial.i18n import _
34 import errno, re
38 from mercurial import (
39 cmdutil,
40 util,
41 )
35 42
36 43 cmdtable = {}
37 44 command = cmdutil.command(cmdtable)
38 45 # Note for extension authors: ONLY specify testedwith = 'internal' for
39 46 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
40 47 # be specifying the version(s) of Mercurial they are tested with, or
41 48 # leave the attribute unspecified.
42 49 testedwith = 'internal'
43 50 lastblackbox = None
44 51
45 52 def wrapui(ui):
46 53 class blackboxui(ui.__class__):
47 54 @util.propertycache
48 55 def track(self):
49 56 return self.configlist('blackbox', 'track', ['*'])
50 57
51 58 def _openlogfile(self):
52 59 def rotate(oldpath, newpath):
53 60 try:
54 61 self._bbvfs.unlink(newpath)
55 62 except OSError as err:
56 63 if err.errno != errno.ENOENT:
57 64 self.debug("warning: cannot remove '%s': %s\n" %
58 65 (newpath, err.strerror))
59 66 try:
60 67 if newpath:
61 68 self._bbvfs.rename(oldpath, newpath)
62 69 except OSError as err:
63 70 if err.errno != errno.ENOENT:
64 71 self.debug("warning: cannot rename '%s' to '%s': %s\n" %
65 72 (newpath, oldpath, err.strerror))
66 73
67 74 fp = self._bbvfs('blackbox.log', 'a')
68 75 maxsize = self.configbytes('blackbox', 'maxsize', 1048576)
69 76 if maxsize > 0:
70 77 st = self._bbvfs.fstat(fp)
71 78 if st.st_size >= maxsize:
72 79 path = fp.name
73 80 fp.close()
74 81 maxfiles = self.configint('blackbox', 'maxfiles', 7)
75 82 for i in xrange(maxfiles - 1, 1, -1):
76 83 rotate(oldpath='%s.%d' % (path, i - 1),
77 84 newpath='%s.%d' % (path, i))
78 85 rotate(oldpath=path,
79 86 newpath=maxfiles > 0 and path + '.1')
80 87 fp = self._bbvfs('blackbox.log', 'a')
81 88 return fp
82 89
83 90 def log(self, event, *msg, **opts):
84 91 global lastblackbox
85 92 super(blackboxui, self).log(event, *msg, **opts)
86 93
87 94 if not '*' in self.track and not event in self.track:
88 95 return
89 96
90 97 if util.safehasattr(self, '_blackbox'):
91 98 blackbox = self._blackbox
92 99 elif util.safehasattr(self, '_bbvfs'):
93 100 try:
94 101 self._blackbox = self._openlogfile()
95 102 except (IOError, OSError) as err:
96 103 self.debug('warning: cannot write to blackbox.log: %s\n' %
97 104 err.strerror)
98 105 del self._bbvfs
99 106 self._blackbox = None
100 107 blackbox = self._blackbox
101 108 else:
102 109 # certain ui instances exist outside the context of
103 110 # a repo, so just default to the last blackbox that
104 111 # was seen.
105 112 blackbox = lastblackbox
106 113
107 114 if blackbox:
108 115 date = util.datestr(None, '%Y/%m/%d %H:%M:%S')
109 116 user = util.getuser()
110 117 pid = str(util.getpid())
111 118 formattedmsg = msg[0] % msg[1:]
112 119 try:
113 120 blackbox.write('%s %s (%s)> %s' %
114 121 (date, user, pid, formattedmsg))
115 122 blackbox.flush()
116 123 except IOError as err:
117 124 self.debug('warning: cannot write to blackbox.log: %s\n' %
118 125 err.strerror)
119 126 lastblackbox = blackbox
120 127
121 128 def setrepo(self, repo):
122 129 self._bbvfs = repo.vfs
123 130
124 131 ui.__class__ = blackboxui
125 132
126 133 def uisetup(ui):
127 134 wrapui(ui)
128 135
129 136 def reposetup(ui, repo):
130 137 # During 'hg pull' a httppeer repo is created to represent the remote repo.
131 138 # It doesn't have a .hg directory to put a blackbox in, so we don't do
132 139 # the blackbox setup for it.
133 140 if not repo.local():
134 141 return
135 142
136 143 if util.safehasattr(ui, 'setrepo'):
137 144 ui.setrepo(repo)
138 145
139 146 @command('^blackbox',
140 147 [('l', 'limit', 10, _('the number of events to show')),
141 148 ],
142 149 _('hg blackbox [OPTION]...'))
143 150 def blackbox(ui, repo, *revs, **opts):
144 151 '''view the recent repository events
145 152 '''
146 153
147 154 if not repo.vfs.exists('blackbox.log'):
148 155 return
149 156
150 157 limit = opts.get('limit')
151 158 blackbox = repo.vfs('blackbox.log', 'r')
152 159 lines = blackbox.read().split('\n')
153 160
154 161 count = 0
155 162 output = []
156 163 for line in reversed(lines):
157 164 if count >= limit:
158 165 break
159 166
160 167 # count the commands by matching lines like: 2013/01/23 19:13:36 root>
161 168 if re.match('^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} .*> .*', line):
162 169 count += 1
163 170 output.append(line)
164 171
165 172 ui.status('\n'.join(reversed(output)))
@@ -1,180 +1,179 b''
1 1 #require test-repo
2 2
3 3 $ cd "$TESTDIR"/..
4 4
5 5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 6 contrib/casesmash.py not using absolute_import
7 7 contrib/check-code.py not using absolute_import
8 8 contrib/check-code.py requires print_function
9 9 contrib/check-config.py not using absolute_import
10 10 contrib/check-config.py requires print_function
11 11 contrib/debugcmdserver.py not using absolute_import
12 12 contrib/debugcmdserver.py requires print_function
13 13 contrib/debugshell.py not using absolute_import
14 14 contrib/fixpax.py not using absolute_import
15 15 contrib/fixpax.py requires print_function
16 16 contrib/hgclient.py not using absolute_import
17 17 contrib/hgclient.py requires print_function
18 18 contrib/hgfixes/fix_bytes.py not using absolute_import
19 19 contrib/hgfixes/fix_bytesmod.py not using absolute_import
20 20 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
21 21 contrib/import-checker.py not using absolute_import
22 22 contrib/import-checker.py requires print_function
23 23 contrib/memory.py not using absolute_import
24 24 contrib/perf.py not using absolute_import
25 25 contrib/python-hook-examples.py not using absolute_import
26 26 contrib/revsetbenchmarks.py not using absolute_import
27 27 contrib/revsetbenchmarks.py requires print_function
28 28 contrib/showstack.py not using absolute_import
29 29 contrib/synthrepo.py not using absolute_import
30 30 contrib/win32/hgwebdir_wsgi.py not using absolute_import
31 31 doc/check-seclevel.py not using absolute_import
32 32 doc/gendoc.py not using absolute_import
33 33 doc/hgmanpage.py not using absolute_import
34 34 hgext/__init__.py not using absolute_import
35 hgext/blackbox.py not using absolute_import
36 35 hgext/bugzilla.py not using absolute_import
37 36 hgext/censor.py not using absolute_import
38 37 hgext/children.py not using absolute_import
39 38 hgext/churn.py not using absolute_import
40 39 hgext/clonebundles.py not using absolute_import
41 40 hgext/color.py not using absolute_import
42 41 hgext/convert/__init__.py not using absolute_import
43 42 hgext/convert/bzr.py not using absolute_import
44 43 hgext/convert/common.py not using absolute_import
45 44 hgext/convert/convcmd.py not using absolute_import
46 45 hgext/convert/cvs.py not using absolute_import
47 46 hgext/convert/cvsps.py not using absolute_import
48 47 hgext/convert/darcs.py not using absolute_import
49 48 hgext/convert/filemap.py not using absolute_import
50 49 hgext/convert/git.py not using absolute_import
51 50 hgext/convert/gnuarch.py not using absolute_import
52 51 hgext/convert/hg.py not using absolute_import
53 52 hgext/convert/monotone.py not using absolute_import
54 53 hgext/convert/p4.py not using absolute_import
55 54 hgext/convert/subversion.py not using absolute_import
56 55 hgext/convert/transport.py not using absolute_import
57 56 hgext/eol.py not using absolute_import
58 57 hgext/extdiff.py not using absolute_import
59 58 hgext/factotum.py not using absolute_import
60 59 hgext/fetch.py not using absolute_import
61 60 hgext/gpg.py not using absolute_import
62 61 hgext/graphlog.py not using absolute_import
63 62 hgext/hgcia.py not using absolute_import
64 63 hgext/hgk.py not using absolute_import
65 64 hgext/highlight/__init__.py not using absolute_import
66 65 hgext/highlight/highlight.py not using absolute_import
67 66 hgext/histedit.py not using absolute_import
68 67 hgext/keyword.py not using absolute_import
69 68 hgext/largefiles/__init__.py not using absolute_import
70 69 hgext/largefiles/basestore.py not using absolute_import
71 70 hgext/largefiles/lfcommands.py not using absolute_import
72 71 hgext/largefiles/lfutil.py not using absolute_import
73 72 hgext/largefiles/localstore.py not using absolute_import
74 73 hgext/largefiles/overrides.py not using absolute_import
75 74 hgext/largefiles/proto.py not using absolute_import
76 75 hgext/largefiles/remotestore.py not using absolute_import
77 76 hgext/largefiles/reposetup.py not using absolute_import
78 77 hgext/largefiles/uisetup.py not using absolute_import
79 78 hgext/largefiles/wirestore.py not using absolute_import
80 79 hgext/mq.py not using absolute_import
81 80 hgext/notify.py not using absolute_import
82 81 hgext/pager.py not using absolute_import
83 82 hgext/patchbomb.py not using absolute_import
84 83 hgext/purge.py not using absolute_import
85 84 hgext/rebase.py not using absolute_import
86 85 hgext/record.py not using absolute_import
87 86 hgext/relink.py not using absolute_import
88 87 hgext/schemes.py not using absolute_import
89 88 hgext/share.py not using absolute_import
90 89 hgext/shelve.py not using absolute_import
91 90 hgext/strip.py not using absolute_import
92 91 hgext/transplant.py not using absolute_import
93 92 hgext/win32mbcs.py not using absolute_import
94 93 hgext/win32text.py not using absolute_import
95 94 hgext/zeroconf/Zeroconf.py not using absolute_import
96 95 hgext/zeroconf/Zeroconf.py requires print_function
97 96 hgext/zeroconf/__init__.py not using absolute_import
98 97 i18n/check-translation.py not using absolute_import
99 98 i18n/polib.py not using absolute_import
100 99 mercurial/cmdutil.py not using absolute_import
101 100 mercurial/commands.py not using absolute_import
102 101 setup.py not using absolute_import
103 102 tests/filterpyflakes.py requires print_function
104 103 tests/generate-working-copy-states.py requires print_function
105 104 tests/get-with-headers.py requires print_function
106 105 tests/heredoctest.py requires print_function
107 106 tests/hypothesishelpers.py not using absolute_import
108 107 tests/hypothesishelpers.py requires print_function
109 108 tests/killdaemons.py not using absolute_import
110 109 tests/md5sum.py not using absolute_import
111 110 tests/mockblackbox.py not using absolute_import
112 111 tests/printenv.py not using absolute_import
113 112 tests/readlink.py not using absolute_import
114 113 tests/readlink.py requires print_function
115 114 tests/revlog-formatv0.py not using absolute_import
116 115 tests/run-tests.py not using absolute_import
117 116 tests/seq.py not using absolute_import
118 117 tests/seq.py requires print_function
119 118 tests/silenttestrunner.py not using absolute_import
120 119 tests/silenttestrunner.py requires print_function
121 120 tests/sitecustomize.py not using absolute_import
122 121 tests/svn-safe-append.py not using absolute_import
123 122 tests/svnxml.py not using absolute_import
124 123 tests/test-ancestor.py requires print_function
125 124 tests/test-atomictempfile.py not using absolute_import
126 125 tests/test-batching.py not using absolute_import
127 126 tests/test-batching.py requires print_function
128 127 tests/test-bdiff.py not using absolute_import
129 128 tests/test-bdiff.py requires print_function
130 129 tests/test-context.py not using absolute_import
131 130 tests/test-context.py requires print_function
132 131 tests/test-demandimport.py not using absolute_import
133 132 tests/test-demandimport.py requires print_function
134 133 tests/test-dispatch.py not using absolute_import
135 134 tests/test-dispatch.py requires print_function
136 135 tests/test-doctest.py not using absolute_import
137 136 tests/test-duplicateoptions.py not using absolute_import
138 137 tests/test-duplicateoptions.py requires print_function
139 138 tests/test-filecache.py not using absolute_import
140 139 tests/test-filecache.py requires print_function
141 140 tests/test-filelog.py not using absolute_import
142 141 tests/test-filelog.py requires print_function
143 142 tests/test-hg-parseurl.py not using absolute_import
144 143 tests/test-hg-parseurl.py requires print_function
145 144 tests/test-hgweb-auth.py not using absolute_import
146 145 tests/test-hgweb-auth.py requires print_function
147 146 tests/test-hgwebdir-paths.py not using absolute_import
148 147 tests/test-hybridencode.py not using absolute_import
149 148 tests/test-hybridencode.py requires print_function
150 149 tests/test-lrucachedict.py not using absolute_import
151 150 tests/test-lrucachedict.py requires print_function
152 151 tests/test-manifest.py not using absolute_import
153 152 tests/test-minirst.py not using absolute_import
154 153 tests/test-minirst.py requires print_function
155 154 tests/test-parseindex2.py not using absolute_import
156 155 tests/test-parseindex2.py requires print_function
157 156 tests/test-pathencode.py not using absolute_import
158 157 tests/test-pathencode.py requires print_function
159 158 tests/test-propertycache.py not using absolute_import
160 159 tests/test-propertycache.py requires print_function
161 160 tests/test-revlog-ancestry.py not using absolute_import
162 161 tests/test-revlog-ancestry.py requires print_function
163 162 tests/test-run-tests.py not using absolute_import
164 163 tests/test-simplemerge.py not using absolute_import
165 164 tests/test-status-inprocess.py not using absolute_import
166 165 tests/test-status-inprocess.py requires print_function
167 166 tests/test-symlink-os-yes-fs-no.py not using absolute_import
168 167 tests/test-trusted.py not using absolute_import
169 168 tests/test-trusted.py requires print_function
170 169 tests/test-ui-color.py not using absolute_import
171 170 tests/test-ui-color.py requires print_function
172 171 tests/test-ui-config.py not using absolute_import
173 172 tests/test-ui-config.py requires print_function
174 173 tests/test-ui-verbosity.py not using absolute_import
175 174 tests/test-ui-verbosity.py requires print_function
176 175 tests/test-url.py not using absolute_import
177 176 tests/test-url.py requires print_function
178 177 tests/test-walkrepo.py requires print_function
179 178 tests/test-wireproto.py requires print_function
180 179 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now