##// END OF EJS Templates
nodemap: check that a simple lookup works fine...
nodemap: check that a simple lookup works fine I realised the code was not exercised much. Differential Revision: https://phab.mercurial-scm.org/D8180

File last commit:

r43347:687b865b default
r44954:23df5ecf default
Show More
loggingutil.py
141 lines | 3.9 KiB | text/x-python | PythonLexer
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 # loggingutil.py - utility for logging events
#
# Copyright 2010 Nicolas Dumazet
# Copyright 2013 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import errno
Augie Fackler
formatting: blacken the codebase...
r43346 from . import pycompat
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830
Yuya Nishihara
loggingutil: add basic logger backends...
r40856 from .utils import (
dateutil,
procutil,
stringutil,
)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 def openlogfile(ui, vfs, name, maxfiles=0, maxsize=0):
Yuya Nishihara
loggingutil: document openlogfile()...
r40831 """Open log file in append mode, with optional rotation
If maxsize > 0, the log file will be rotated up to maxfiles.
"""
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 def rotate(oldpath, newpath):
try:
vfs.unlink(newpath)
except OSError as err:
if err.errno != errno.ENOENT:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"warning: cannot remove '%s': %s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (newpath, err.strerror)
)
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 try:
if newpath:
vfs.rename(oldpath, newpath)
except OSError as err:
if err.errno != errno.ENOENT:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"warning: cannot rename '%s' to '%s': %s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (newpath, oldpath, err.strerror)
)
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830
if maxsize > 0:
try:
st = vfs.stat(name)
except OSError:
pass
else:
if st.st_size >= maxsize:
path = vfs.join(name)
for i in pycompat.xrange(maxfiles - 1, 1, -1):
Augie Fackler
formatting: blacken the codebase...
r43346 rotate(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 oldpath=b'%s.%d' % (path, i - 1),
newpath=b'%s.%d' % (path, i),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rotate(oldpath=path, newpath=maxfiles > 0 and path + b'.1')
return vfs(name, b'a', makeparentdirs=False)
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
loggingutil: add basic logger backends...
r40856 def _formatlogline(msg):
date = dateutil.datestr(format=b'%Y/%m/%d %H:%M:%S')
pid = procutil.getpid()
return b'%s (%d)> %s' % (date, pid, msg)
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
loggingutil: add basic logger backends...
r40856 def _matchevent(event, tracked):
return b'*' in tracked or event in tracked
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
loggingutil: add basic logger backends...
r40856 class filelogger(object):
"""Basic logger backed by physical file with optional rotation"""
def __init__(self, vfs, name, tracked, maxfiles=0, maxsize=0):
self._vfs = vfs
self._name = name
self._trackedevents = set(tracked)
self._maxfiles = maxfiles
self._maxsize = maxsize
def tracked(self, event):
return _matchevent(event, self._trackedevents)
def log(self, ui, event, msg, opts):
line = _formatlogline(msg)
try:
Augie Fackler
formatting: blacken the codebase...
r43346 with openlogfile(
ui,
self._vfs,
self._name,
maxfiles=self._maxfiles,
maxsize=self._maxsize,
) as fp:
Yuya Nishihara
loggingutil: add basic logger backends...
r40856 fp.write(line)
except IOError as err:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
b'cannot write to %s: %s\n'
% (self._name, stringutil.forcebytestr(err))
)
Yuya Nishihara
loggingutil: add basic logger backends...
r40856
class fileobjectlogger(object):
"""Basic logger backed by file-like object"""
def __init__(self, fp, tracked):
self._fp = fp
self._trackedevents = set(tracked)
def tracked(self, event):
return _matchevent(event, self._trackedevents)
def log(self, ui, event, msg, opts):
line = _formatlogline(msg)
try:
self._fp.write(line)
self._fp.flush()
except IOError as err:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
b'cannot write to %s: %s\n'
% (
stringutil.forcebytestr(self._fp.name),
stringutil.forcebytestr(err),
)
)
Yuya Nishihara
loggingutil: add basic logger backends...
r40856
Yuya Nishihara
loggingutil: extract openlogfile() and proxylogger to new module...
r40830 class proxylogger(object):
"""Forward log events to another logger to be set later"""
def __init__(self):
self.logger = None
def tracked(self, event):
return self.logger is not None and self.logger.tracked(event)
def log(self, ui, event, msg, opts):
assert self.logger is not None
self.logger.log(ui, event, msg, opts)