def __init__(self, stream): """Constructor stream[in] A file type The stream argument must be a valid file type supporting for example the readline()-method. For example, the return of the buildin function open() can be used: LogParserBase(open("/path/to/mysql.log")) Raises LogParserError on errors. """ self._stream = None self._version = None self._program = None self._port = None self._socket = None self._start_datetime = None self._last_seen_datetime = None # Check if we got a file type line = None try: self._stream = stream line = self._get_next_line() except AttributeError: raise LogParserError("Need a file type") # Not every log file starts with a header if line is not None and line.endswith('started with:'): self._parse_header(line) else: self._stream.seek(0)
def _parse_header(self, line): """Parse the header of a MySQL log file line[in] A string, usually result of self._get_next_line() This method parses the header of a MySQL log file, that is the header found in the General and Slow Query log files. It sets attributes _version, _program, _port and _socket. Note that headers can repeat in a log file, for example, after a restart of the MySQL server. Example header: /usr/sbin/mysqld, Version: 5.5.17-log (Source distribution). started with: Tcp port: 0 Unix socket: /tmp/mysql.sock Time Id Command Argument Raises LogParserError on errors. """ if line is None: return # Header line containing executable and version, example: # /raid0/mysql/mysql/bin/mysqld, # Version: 5.5.17-log (Source distribution). started with: info = _HEADER_VERSION_CRE.match(line) if not info: raise LogParserError("Could not read executable and version from " "header") program, major, minor, patch, extra = info.groups() # Header line with server information, example: # Tcp port: 3306 Unix socket: /tmp/mysql.sock line = self._get_next_line() info = _HEADER_SERVER_CRE.match(line) if not info: raise LogParserError("Malformed server header line: %s" % line) tcp_port, unix_socket = info.groups() # Throw away column header line, example: # Time Id Command Argument self._get_next_line() self._version = (int(major), int(minor), int(patch), extra) self._program = program self._port = int(tcp_port) self._socket = unix_socket
def _parse_line(regex, line): """Parses a log line using given regular expression regex[in] a SRE_Match-object line[in] a string This function takes a log line and matches the regular expresion given with the regex argument. It returns the result of re.MatchObject.groups(), which is a tuple. Raises LogParserError on errors. Returns a tuple. """ info = regex.match(line) if info is None: raise LogParserError('Failed parsing Slow Query line: %s' % line[:30]) return info.groups()
def _parse_command(self, logentry, entry): """Parse a log entry from the General Query Log logentry[in] a string or tuple entry[in] an instance of GeneralQueryLogEntry The logentry-parameter is either a line read from the log file or the result of a previous attempt to read a command. The entry argument should be an instance of GeneralQueryLogEntry. It returns the entry or None if nothing could be read. Raises LogParserError on errors. Returns the GeneralQueryLogEntry-instance or None """ if logentry is None: return None if isinstance(logentry, tuple): dt, session_id, command, argument = logentry elif logentry.endswith('started with:'): while logentry.endswith('started with:'): # We got a header self._parse_header(logentry) logentry = self._get_next_line() if logentry is None: return None return self._parse_command(logentry, entry) else: info = _GENERAL_ENTRY_CRE.match(logentry) if info is None: raise LogParserError("Failed parsing command line: %s" % logentry) dt, session_id, command, argument = info.groups() self._cached_logentry = None session_id = int(session_id) entry['session_id'] = session_id try: session = self._sessions[session_id] except KeyError: session = self._new_session(session_id) entry['command'] = command if dt is not None: #entry['datetime'] = datetime.datetime.strptime(dt,"%y%m%d %H:%M:%S") entry['datetime'] = datetime.datetime.strptime( dt, "%Y-%m-%dT%H:%M:%S.%fZ") session['time_last_action'] = entry['datetime'] else: entry['datetime'] = session['time_last_action'] try: self._commands[command](entry, session, argument) except KeyError: # Generic command entry['argument'] = argument for key in entry.keys(): if key in session: entry[key] = session[key] if session['to_delete'] is True: del self._sessions[session_id] del session return entry