Back to index

moin  1.9.0~rc2
Public Member Functions | Public Attributes
MoinMoin.logfile.eventlog.EventLog Class Reference
Inheritance diagram for MoinMoin.logfile.eventlog.EventLog:
Inheritance graph
[legend]
Collaboration diagram for MoinMoin.logfile.eventlog.EventLog:
Collaboration graph
[legend]

List of all members.

Public Member Functions

def __init__
def add
def parser
def set_filter
def __iter__
def reverse
def sanityCheck
def __getattr__
def size
def lines
def date
def peek
def next
def previous
def to_begin
def to_end
def position
def seek
def line_no
def calculate_line_no
def add

Public Attributes

 filter
 loglevel
 buffer_size

Detailed Description

The global event-log is mainly used for statistics (e.g. EventStats) 

Definition at line 15 of file eventlog.py.


Constructor & Destructor Documentation

def MoinMoin.logfile.eventlog.EventLog.__init__ (   self,
  request,
  filename = None,
  buffer_size = 65536,
  kw 
)

Definition at line 17 of file eventlog.py.

00017 
00018     def __init__(self, request, filename=None, buffer_size=65536, **kw):
00019         if filename is None:
00020             rootpagename = kw.get('rootpagename', None)
00021             if rootpagename:
00022                 from MoinMoin.Page import Page
00023                 filename = Page(request, rootpagename).getPagePath('event-log', isfile=1)
00024             else:
00025                 filename = request.rootpage.getPagePath('event-log', isfile=1)
00026         LogFile.__init__(self, filename, buffer_size)

Here is the call graph for this function:


Member Function Documentation

def MoinMoin.logfile.LogFile.__getattr__ (   self,
  name 
) [inherited]
generate some attributes when needed

Definition at line 130 of file __init__.py.

00130 
00131     def __getattr__(self, name):
00132         """
00133         generate some attributes when needed
00134         """
00135         if name == "_LogFile__rel_index": # Python black magic: this is the real name of the __rel_index attribute
00136             # starting iteration from begin
00137             self.__buffer1 = LineBuffer(self._input, 0, self.buffer_size)
00138             self.__buffer2 = LineBuffer(self._input,
00139                                         self.__buffer1.offsets[-1],
00140                                         self.buffer_size)
00141             self.__buffer = self.__buffer1
00142             self.__rel_index = 0
00143             return 0
00144         elif name == "_input":
00145             try:
00146                 # Open the file (NOT using codecs.open, it breaks our offset calculation. We decode it later.).
00147                 # Use binary mode in order to retain \r - otherwise the offset calculation would fail.
00148                 self._input = file(self.__filename, "rb", )
00149             except IOError, err:
00150                 if err.errno == errno.ENOENT: # "file not found"
00151                     # XXX workaround if edit-log does not exist: just create it empty
00152                     # if this workaround raises another error, we don't catch
00153                     # it, so the admin will see it.
00154                     f = file(self.__filename, "ab")
00155                     f.write('')
00156                     f.close()
00157                     self._input = file(self.__filename, "rb", )
00158                 else:
00159                     logging.error("logfile: %r IOERROR errno %d (%s)" % (self.__filename, err.errno, os.strerror(err.errno)))
00160                     raise
00161             return self._input
00162         elif name == "_output":
00163             self._output = codecs.open(self.__filename, 'a', config.charset)
00164             return self._output
00165         else:
00166             raise AttributeError(name)

def MoinMoin.logfile.LogFile.__iter__ (   self) [inherited]

Definition at line 104 of file __init__.py.

00104 
00105     def __iter__(self):
00106         return self

def MoinMoin.logfile.eventlog.EventLog.add (   self,
  request,
  eventtype,
  values = None,
  add_http_info = 1,
  mtime_usecs = None 
)
Write an event of type `eventtype, with optional key/value
    pairs appended (i.e. you have to pass a dict).

Definition at line 28 of file eventlog.py.

00028 
00029             mtime_usecs=None):
00030         """ Write an event of type `eventtype, with optional key/value
00031             pairs appended (i.e. you have to pass a dict).
00032         """
00033         if request.isSpiderAgent:
00034             return
00035 
00036         if mtime_usecs is None:
00037             mtime_usecs = wikiutil.timestamp2version(time.time())
00038 
00039         if values is None:
00040             values = {}
00041         if request.cfg.log_remote_addr and add_http_info:
00042             # if cfg.log_remote_addr is False (usually for privacy reasons),
00043             # we likely do not want to log user agent and http referer either.
00044             for key in ['remote_addr', 'http_user_agent', 'http_referer']:
00045                 value = getattr(request, key, '')
00046                 if value:
00047                     # Save those http headers in UPPERcase
00048                     values[key.upper()] = value
00049         # Encode values in a query string TODO: use more readable format
00050         values = wikiutil.makeQueryString(values)
00051         self._add(u"%d\t%s\t%s\n" % (mtime_usecs, eventtype, values))

Here is the call graph for this function:

Here is the caller graph for this function:

def MoinMoin.logfile.LogFile.add (   self,
  data 
) [inherited]
add line to log file
This implementation save the values as TAB separated strings.
This method should be overwritten by the sub classes.

Definition at line 442 of file __init__.py.

00442 
00443     def add(self, *data):
00444         """
00445         add line to log file
00446         This implementation save the values as TAB separated strings.
00447         This method should be overwritten by the sub classes.
00448         """
00449         line = "\t".join(data)
00450         self._add(line)

Here is the call graph for this function:

Here is the caller graph for this function:

def MoinMoin.logfile.LogFile.calculate_line_no (   self) [inherited]
Calculate the current line number from buffer offsets

If line number is unknown it is calculated by parsing the whole file.
This may be expensive.

Definition at line 421 of file __init__.py.

00421 
00422     def calculate_line_no(self):
00423         """ Calculate the current line number from buffer offsets
00424 
00425         If line number is unknown it is calculated by parsing the whole file.
00426         This may be expensive.
00427         """
00428         self._input.seek(0, 0)
00429         lines = self._input.read(self.__buffer.offsets[self.__rel_index])
00430         self.__lineno = len(lines.splitlines())
00431         return self.__lineno

def MoinMoin.logfile.LogFile.date (   self) [inherited]
Return timestamp of log file in usecs 

Definition at line 206 of file __init__.py.

00206 
00207     def date(self):
00208         # ToDo check if we need this method
00209         """ Return timestamp of log file in usecs """
00210         try:
00211             mtime = os.path.getmtime(self.__filename)
00212         except OSError, err:
00213             if err.errno == errno.ENOENT:
00214                 # This can happen on fresh wiki when building the index
00215                 # Usually the first request will create an event log
00216                 raise LogMissing(str(err))
00217             raise
00218         return wikiutil.timestamp2version(mtime)

def MoinMoin.logfile.LogFile.line_no (   self) [inherited]
@return: the current line number or None if line number is unknown

Definition at line 417 of file __init__.py.

00417 
00418     def line_no(self):
00419         """@return: the current line number or None if line number is unknown"""
00420         return self.__lineno

def MoinMoin.logfile.LogFile.lines (   self) [inherited]
Return number of lines in the log file

Return 0 if the file does not exist. Raises other OSError.

Expensive for big log files - O(n)

@return: size of log file in lines
@rtype: Int

Definition at line 182 of file __init__.py.

00182 
00183     def lines(self):
00184         """ Return number of lines in the log file
00185 
00186         Return 0 if the file does not exist. Raises other OSError.
00187 
00188         Expensive for big log files - O(n)
00189 
00190         @return: size of log file in lines
00191         @rtype: Int
00192         """
00193         try:
00194             f = file(self.__filename, 'r')
00195             try:
00196                 count = 0
00197                 for line in f:
00198                     count += 1
00199                 return count
00200             finally:
00201                 f.close()
00202         except (OSError, IOError), err:
00203             if err.errno == errno.ENOENT:
00204                 return 0
00205             raise

def MoinMoin.logfile.LogFile.next (   self) [inherited]
get next line that passes through the filter
@return: next entry
raises StopIteration at file end

Definition at line 294 of file __init__.py.

00294 
00295     def next(self):
00296         """get next line that passes through the filter
00297         @return: next entry
00298         raises StopIteration at file end
00299         """
00300         result = None
00301         while result is None:
00302             while result is None:
00303                 logging.log(self.loglevel, "LogFile.next %s" % self.__filename)
00304                 result = self.__next()
00305             if self.filter and not self.filter(result):
00306                 result = None
00307         return result

Here is the call graph for this function:

Here is the caller graph for this function:

def MoinMoin.logfile.eventlog.EventLog.parser (   self,
  line 
)
parse a event-log line into its components 

Reimplemented from MoinMoin.logfile.LogFile.

Definition at line 52 of file eventlog.py.

00052 
00053     def parser(self, line):
00054         """ parse a event-log line into its components """
00055         try:
00056             time_usecs, eventtype, kvpairs = line.rstrip().split('\t')
00057         except ValueError:
00058             # badly formatted line in file, skip it
00059             return None
00060         return long(time_usecs), eventtype, wikiutil.parseQueryString(kvpairs)

def MoinMoin.logfile.LogFile.peek (   self,
  lines 
) [inherited]
Move position in file forward or backwards by "lines" count

It adjusts .__lineno if set.
This function is not aware of filters!

@param lines: number of lines, may be negative to move backward
@rtype: boolean
@return: True if moving more than to the beginning and moving
 to the end or beyond

Definition at line 219 of file __init__.py.

00219 
00220     def peek(self, lines):
00221         """ Move position in file forward or backwards by "lines" count
00222 
00223         It adjusts .__lineno if set.
00224         This function is not aware of filters!
00225 
00226         @param lines: number of lines, may be negative to move backward
00227         @rtype: boolean
00228         @return: True if moving more than to the beginning and moving
00229                  to the end or beyond
00230         """
00231         logging.log(self.loglevel, "LogFile.peek %s" % self.__filename)
00232         self.__rel_index += lines
00233         while self.__rel_index < 0:
00234             if self.__buffer is self.__buffer2:
00235                 if self.__buffer.offsets[0] == 0:
00236                     # already at the beginning of the file
00237                     self.__rel_index = 0
00238                     self.__lineno = 0
00239                     return True
00240                 else:
00241                     # change to buffer 1
00242                     self.__buffer = self.__buffer1
00243                     self.__rel_index += self.__buffer.len
00244             else: # self.__buffer is self.__buffer1
00245                 if self.__buffer.offsets[0] == 0:
00246                     # already at the beginning of the file
00247                     self.__rel_index = 0
00248                     self.__lineno = 0
00249                     return True
00250                 else:
00251                     # load previous lines
00252                     self.__buffer2 = self.__buffer1
00253                     self.__buffer1 = LineBuffer(self._input,
00254                                                 self.__buffer.offsets[0],
00255                                                 self.buffer_size,
00256                                                 forward=False)
00257                     self.__buffer = self.__buffer1
00258                     self.__rel_index += self.__buffer.len
00259 
00260         while self.__rel_index >= self.__buffer.len:
00261             if self.__buffer is self.__buffer1:
00262                 # change to buffer 2
00263                 self.__rel_index -= self.__buffer.len
00264                 self.__buffer = self.__buffer2
00265             else: # self.__buffer is self.__buffer2
00266                 # try to load next buffer
00267                 tmpbuff = LineBuffer(self._input,
00268                                      self.__buffer.offsets[-1],
00269                                      self.buffer_size)
00270                 if tmpbuff.len == 0:
00271                     # end of file
00272                     if self.__lineno is not None:
00273                         self.__lineno += (lines -
00274                                          (self.__rel_index - self.__buffer.len))
00275                     self.__rel_index = self.__buffer.len # point to after last read line
00276                     return True
00277                 # shift buffers
00278                 self.__rel_index -= self.__buffer.len
00279                 self.__buffer1 = self.__buffer2
00280                 self.__buffer2 = tmpbuff
00281                 self.__buffer = self.__buffer2
00282 
00283         if self.__lineno is not None:
00284             self.__lineno += lines
00285         return False

Here is the caller graph for this function:

def MoinMoin.logfile.LogFile.position (   self) [inherited]
Return the current file position

This can be converted into a String using back-ticks and then be rebuild.
For this plain file implementation position is an Integer.

Definition at line 361 of file __init__.py.

00361 
00362     def position(self):
00363         """ Return the current file position
00364 
00365         This can be converted into a String using back-ticks and then be rebuild.
00366         For this plain file implementation position is an Integer.
00367         """
00368         return self.__buffer.offsets[self.__rel_index]

Here is the caller graph for this function:

def MoinMoin.logfile.LogFile.previous (   self) [inherited]
get previous line that passes through the filter
@return: previous entry
raises StopIteration at file begin

Definition at line 314 of file __init__.py.

00314 
00315     def previous(self):
00316         """get previous line that passes through the filter
00317         @return: previous entry
00318         raises StopIteration at file begin
00319         """
00320         result = None
00321         while result is None:
00322             while result is None:
00323                 logging.log(self.loglevel, "LogFile.previous %s" % self.__filename)
00324                 result = self.__previous()
00325             if self.filter and not self.filter(result):
00326                 result = None
00327         return result

Here is the call graph for this function:

Here is the caller graph for this function:

def MoinMoin.logfile.LogFile.reverse (   self) [inherited]
yield log entries in reverse direction starting from last one

@rtype: iterator

Definition at line 107 of file __init__.py.

00107 
00108     def reverse(self):
00109         """ yield log entries in reverse direction starting from last one
00110 
00111         @rtype: iterator
00112         """
00113         self.to_end()
00114         while 1:
00115             try:
00116                 logging.log(self.loglevel, "LogFile.reverse %s" % self.__filename)
00117                 result = self.previous()
00118             except StopIteration:
00119                 return
00120             yield result

Here is the call graph for this function:

def MoinMoin.logfile.LogFile.sanityCheck (   self) [inherited]
Check for log file write access.

@rtype: string (error message) or None

Definition at line 121 of file __init__.py.

00121 
00122     def sanityCheck(self):
00123         """ Check for log file write access.
00124 
00125         @rtype: string (error message) or None
00126         """
00127         if not os.access(self.__filename, os.W_OK):
00128             return "The log '%s' is not writable!" % (self.__filename, )
00129         return None

def MoinMoin.logfile.LogFile.seek (   self,
  position,
  line_no = None 
) [inherited]
moves file position to an value formerly gotten from .position().
To enable line counting line_no must be provided.
.seek is much more efficient for moving long distances than .peek.
raises ValueError if position is invalid

Definition at line 369 of file __init__.py.

00369 
00370     def seek(self, position, line_no=None):
00371         """ moves file position to an value formerly gotten from .position().
00372         To enable line counting line_no must be provided.
00373         .seek is much more efficient for moving long distances than .peek.
00374         raises ValueError if position is invalid
00375         """
00376         logging.log(self.loglevel, "LogFile.seek %s pos %d" % (self.__filename, position))
00377         if self.__buffer1:
00378             logging.log(self.loglevel, "b1 %r %r" % (self.__buffer1.offsets[0], self.__buffer1.offsets[-1]))
00379         if self.__buffer2:
00380             logging.log(self.loglevel, "b2 %r %r" % (self.__buffer2.offsets[0], self.__buffer2.offsets[-1]))
00381         if self.__buffer1 and self.__buffer1.offsets[0] <= position < self.__buffer1.offsets[-1]:
00382             # position is in .__buffer1
00383             self.__rel_index = self.__buffer1.offsets.index(position)
00384             self.__buffer = self.__buffer1
00385         elif self.__buffer2 and self.__buffer2.offsets[0] <= position < self.__buffer2.offsets[-1]:
00386             # position is in .__buffer2
00387             self.__rel_index = self.__buffer2.offsets.index(position)
00388             self.__buffer = self.__buffer2
00389         elif self.__buffer1 and self.__buffer1.offsets[-1] == position:
00390             # we already have one buffer directly before where we want to go
00391             self.__buffer2 = LineBuffer(self._input,
00392                                         position,
00393                                         self.buffer_size)
00394             self.__buffer = self.__buffer2
00395             self.__rel_index = 0
00396         elif self.__buffer2 and self.__buffer2.offsets[-1] == position:
00397             # we already have one buffer directly before where we want to go
00398             self.__buffer1 = self.__buffer2
00399             self.__buffer2 = LineBuffer(self._input,
00400                                         position,
00401                                         self.buffer_size)
00402             self.__buffer = self.__buffer2
00403             self.__rel_index = 0
00404         else:
00405             # load buffers around position
00406             self.__buffer1 = LineBuffer(self._input,
00407                                         position,
00408                                         self.buffer_size,
00409                                         forward=False)
00410             self.__buffer2 = LineBuffer(self._input,
00411                                         position,
00412                                         self.buffer_size)
00413             self.__buffer = self.__buffer2
00414             self.__rel_index = 0
00415             # XXX test for valid position
00416         self.__lineno = line_no

Here is the caller graph for this function:

def MoinMoin.logfile.eventlog.EventLog.set_filter (   self,
  event_types = None 
)
optionally filter log for specific event types 

Definition at line 61 of file eventlog.py.

00061 
00062     def set_filter(self, event_types=None):
00063         """ optionally filter log for specific event types """
00064         if event_types is None:
00065             self.filter = None
00066         else:
00067             self.filter = lambda line: (line[1] in event_types)
00068 
00069 
def MoinMoin.logfile.LogFile.size (   self) [inherited]
Return log size in bytes

Return 0 if the file does not exist. Raises other OSError.

@return: size of log file in bytes
@rtype: Int

Definition at line 167 of file __init__.py.

00167 
00168     def size(self):
00169         """ Return log size in bytes
00170 
00171         Return 0 if the file does not exist. Raises other OSError.
00172 
00173         @return: size of log file in bytes
00174         @rtype: Int
00175         """
00176         try:
00177             return os.path.getsize(self.__filename)
00178         except OSError, err:
00179             if err.errno == errno.ENOENT:
00180                 return 0
00181             raise

def MoinMoin.logfile.LogFile.to_begin (   self) [inherited]
moves file position to the begin

Definition at line 328 of file __init__.py.

00328 
00329     def to_begin(self):
00330         """moves file position to the begin"""
00331         logging.log(self.loglevel, "LogFile.to_begin %s" % self.__filename)
00332         if self.__buffer1 is None or self.__buffer1.offsets[0] != 0:
00333             self.__buffer1 = LineBuffer(self._input,
00334                                         0,
00335                                         self.buffer_size)
00336             self.__buffer2 = LineBuffer(self._input,
00337                                         self.__buffer1.offsets[-1],
00338                                         self.buffer_size)
00339         self.__buffer = self.__buffer1
00340         self.__rel_index = 0
00341         self.__lineno = 0

def MoinMoin.logfile.LogFile.to_end (   self) [inherited]
moves file position to the end

Definition at line 342 of file __init__.py.

00342 
00343     def to_end(self):
00344         """moves file position to the end"""
00345         logging.log(self.loglevel, "LogFile.to_end %s" % self.__filename)
00346         self._input.seek(0, 2) # to end of file
00347         size = self._input.tell()
00348         if self.__buffer2 is None or size > self.__buffer2.offsets[-1]:
00349             self.__buffer2 = LineBuffer(self._input,
00350                                         size,
00351                                         self.buffer_size,
00352                                         forward=False)
00353 
00354             self.__buffer1 = LineBuffer(self._input,
00355                                         self.__buffer2.offsets[0],
00356                                         self.buffer_size,
00357                                         forward=False)
00358         self.__buffer = self.__buffer2
00359         self.__rel_index = self.__buffer2.len
00360         self.__lineno = None

Here is the caller graph for this function:


Member Data Documentation

Definition at line 100 of file __init__.py.

Reimplemented from MoinMoin.logfile.LogFile.

Definition at line 64 of file eventlog.py.

Definition at line 95 of file __init__.py.


The documentation for this class was generated from the following file: