XׯdjqXdZddlZddlmZmZmZddlmZmZm Z ddl m Z m Z m Z ddlmZddlZddlZddlZdZGdd eZGd d eZGd d eZGddeZGddeZGddeZGddeZGddeZdS)a .. module:: wb_log_reader :synopsis: Reads and parses a log source to retrieve sets of records from it. This module defines several classes to handle MySQL server logs. It supports logs stored in the database as well as logs stored in files. All of the defined classes adhere to a common interface defining and implementing these public attributes and methods: Attributes: column_specs (tuple): Specifies each field in the log entries. The elements of this tuple are also tuples having the form (column_name, column_widh, [column_table_name]) where: column_name (str): A human readable name for the column. Frontend code should use this name wherever a column title is needed. column_width (int): The recommended with of the column column_table_name (str): (Optional) the name of the field referred by this column in the log table for DB logs partial_support: False if the log source is fully supported or a string explaining the limitations regarding the implemented log source reader class otherwise. Methods: has_previous(): Returns True if there are older entries that can be retrieved and False otherwise. has_next(): Returns True if there are newer entries that can be retrieved and False otherwise. first(): Returns a list of the first (oldest) records in the log. Each element in this list represents a single log entry and is also a list whose elements are the values for the columns defined in `column_specs`. last(): The same as `first()` but the records returned are the newest ones. previous(): Returns the records that precede the last retrieved records. Before calling it you should verify that `has_previous()` returns True. next(): Returns the records that follow the last retrieved records. Before calling it you should verify that `has_next()` returns True. current(): Returns the last retrieved records. range_text(): Returns a string that gives an indication of the position of the current records in the existent log set (if available). E.g. 'Records 1..50 of 145' refresh(): After calling this function the log reader should be able to manage new log entries that were added since the last call to this function or since the creation of the log reader object. This function doesn't return anything. If it is not possible to read the log entries, the class should raise an exception with a descriptive message to let the user know the reasons of the failure. Current limitations: ---------------------- * No remote server support for logs stored in files. * Cannot read files that aren't readable by the user running Workbench. N)log_info log_error log_warning)SudoTailInputFileLocalInputFile SFTPInputFile)LogFileAccessError ServerIOErrorInvalidPasswordError)server_os_pathc|ddkr |dd}d|vr|d\}}}d|z}nd} tjtj|d}t j|t j||zS#t$r"}td|d|d|cYd}~Sd}~wwxYw) NZ.z%Y-%m-%dT%H:%M:%SzError parsing timestamp z:  ) partitioncalendartimegmdatetimestrptime timetupletimestrftime localtime Exceptionr)tsfmt_ms local_timees ..\modules\wb_log_reader.pyts_iso_to_localr$ns "v}} W byyLL%% Ar V _X%6%?%?DW%X%X%b%b%d%dee }S$."<"<==b@@  """aaa@AAA sA-B++ C5C CCcZeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdS)BaseQueryLogReaderzo The base class for logs stored in a database. **This is not intended for direct instantiation.** c||_d|_||_||_||_d|_d|_|d|_t|j|jz d|_ d|D|_ dS)aConstructor :param ctrl_be: Control backend instance to make queries :param log_table: The name of the table where the log entries are stored :type log_table: str :param column_specs: Column definitions as explained in the module docstring :type column_specs: tuple :param ordering_column: The index for the column in `column_specs` that stores the timestamp of the log entries :type ordering_column: int NFr2cg|] }|d S)).0colspecs r# z/BaseQueryLogReader.__init__..sBBB'!*BBB) log_tablelog_filectrl_be column_specsordering_columnpartial_support total_countrefresh show_countmax show_startcolnames)selfr2r0r3r4s r#__init__zBaseQueryLogReader.__init__s#  (.$ d.@!DDBBLBBB r/c|jdkSNr)r:r<s r# has_previouszBaseQueryLogReader.has_previouss""r/c(|j|jdz kS)N)r:r6r@s r#has_nextzBaseQueryLogReader.has_nexts!1A!555r/c*|SN)_query_recordsr@s r#currentzBaseQueryLogReader.currents""$$$r/cnt|j|jz d|_|Sr?)r9r:r8rGr@s r#previouszBaseQueryLogReader.previouss.do?CC""$$$r/cxt|j|jz|j|_|SrF)minr:r8r6rGr@s r#__next__zBaseQueryLogReader.__next__s1do?AQRR""$$$r/c8d|_|Sr?)r:rGr@s r#firstzBaseQueryLogReader.firsts""$$$r/cnt|j|jz d|_|Sr?)r9r6r8r:rGr@s r#lastzBaseQueryLogReader.lasts/d.@!DD""$$$r/cd|jzS)Nz %d records)r6r@s r# size_textzBaseQueryLogReader.size_textsd...r/cfd|jt|j|jz|j|jfzS)NzRecords %d..%d of %d)r:rLr8r6r@s r# range_textzBaseQueryLogReader.range_texts8%),T_t-NPTP`)a)a)-)9);; ;r/c |jd|jz}n$#t$r}t d|zd}~wwxYw|r|st d|d|_dS)Nz SELECT count(*) AS count FROM %sError fetching log contents: %szError fetching log contentscount)r2 exec_queryr0rr nextRow intByNamer6)r<resultr"s r#r7zBaseQueryLogReader.refreshs G\,,-ORVR`-`aaFF G G G AA EFF F G ?V^^-- ? =>> >!++G44s"% AAAcd|j|j|j|j|jfz} |j|n$#t$r}td|zd}~wwxYwg}rQ r<fd|jD}| | .s'SSS++G44SSSr/z1There were problems querying the server table %s.) r0r;r4r:r8r2rYrr rZappendr6IOError)r<queryr"recordsrowr\s @r#rGz!BaseQueryLogReader._query_recordss@ d&:; E))  G\,,U33FF G G G AA EFF F G  `.."" $SSSSDMSSSs###.."" $  `MPTP^^__ _sA A'A""A'N)__name__ __module__ __qualname____doc__r=rArDrHrJrMrOrQrSrUr7rGr+r/r#r&r&s CCC4###666%%%%%%%%%%%%%%%///;;; 555r/r&c eZdZdfd ZxZS)GeneralQueryLogReadermysql.general_logcpd}d|_tt||||ddS)N))Time event_timeFromx user_host)ThreadP thread_id)Serverrv server_id) Command Typerv command_type)Detailargumentr) detail_columnsuperrkr=r<r2 table_namer3 __class__s r#r=zGeneralQueryLogReader.__init__s@  #T**33GZWXYYYYYr/)rlrfrgrhr= __classcell__rs@r#rkrksG Z Z Z Z Z Z Z Z Z Zr/rkc eZdZdfd ZxZS)SlowQueryLogReadermysql.slow_logcpd}d|_tt||||ddS)N) ) Start Timero start_timerq) Query Timero query_time) Lock Timero lock_time) Rows Sentr( rows_sent) Rows Examinedr( rows_examined)DBrvdb)zLast Insert IDr(last_insert_id)z Insert IDr( insert_id)z Server IDr(ry)SQLr}sql_text r)rrrr=rs r#r=zSlowQueryLogReader.__init__s@     $''00*lTUVVVVVr/)rrrs@r#rrsGWWWWWWWWWWr/rcHeZdZdZdZedZdZdZdZ dZ dS) EventLogInputc"||_d|_dS)Nstderr)r2path)r<r2rs r#r=zEventLogInput.__init__s  r/cdSr?r+r@s r#tellzEventLogInput.tellsqr/cdSr?r+r@s r#sizezEventLogInput.size sqr/cdSNrr+)r<startends r# get_rangezEventLogInput.get_rangerr/cdSrr+)r<offsets r#start_read_fromzEventLogInput.start_read_fromrr/cdSrr+)r<rXs r#readzEventLogInput.readrr/cdSrr+r@s r#readlinezEventLogInput.readlinerr/N) rfrgrhr=rpropertyrrrrrr+r/r#rrsXr/rczeZdZdZddZdZdZdZdZdZ d Z d Z d Z d Z d ZdZdZdZdZdZdZdS)BaseLogFileReaderz The base class for logs stored in files unreadable to the current user. **This is not intended for direct instantiation.** Tc||_||_||_||_||_d|_|d}t|jj}|jjj }|s.| r|j d}| |r|n| |||_d} d} |jjjrpd} |dkrd} |jjjsB|jjjst'd|jjjst'dd} nd|jjj} |jjjsB|jjjst'd|jjjst'dd} | rMt-d|jz|jd d } d} t3|jj|j| |_|jj|_nI#t<$r<}| d} n-t?d |z|j d Yd }~nd }~wwxYw| r|jd d } t3|jj|j| |_|jj|_n#t<$r2}t?d |z|j d d }~wwxYwn| rQ|jjjst'd tC|j|j|_|jj|_n| rHt-d|jztE|j|j|_|jj|_nAt-d|jztG|j|_|jj|_||_$tKd|j|z |_&|j|_'d|_(|j)d|j$}|*||_+d S)aConstructor :param ctrl_be: Control backend instance to retrieve root password if needed :param log_file_param: The path to the log file to read from or a file like instance to read log entries from :type log_file_param: str/file :param pat: A regular expression pattern that matches a log entry :type pat: regular expression object :param chunk_size: The size in bytes of the chunks that are read from the log file :type chunk_size: int :param truncate_long_lines: Whether the log entries that are long should be abbreviated :type truncate_long_lines: bool :param append_gaps: Whether the data between the end of the record regex and the start of the next record regex should be added to the previous entry :type append_gaps: (not used) Fz "datadirrTzYou have not enabled remote administration for this server. Without it this log file cannot be shown. Please enable remote administration in this server instance and try again.zRemote log files are only supported for SSH connection. Please configure an SSH connection and try again.z4Will use sudo and dd to get contents of log file %s file) cached_onlyNzInvalid password to sudo %s zAn attempt to read events from the remote server failed. Events can only be read from the local machine, hence installed MySQL Workbench on the remote machine to allow showing the server's event log.z-Will use sftp to get contents of log file %s z:Will use plain file access to get contents of log file %s r),patpat2 append_gapstruncate_long_linesr2r5stripr server_profileris_sql_connectedget_server_variableisabsjoin log_file_nametarget_is_windowsloweris_localremote_admin_enabledr uses_sshuse_sudorpassword_handlerget_password_forr server_helperr1r file_sizer rreset_password_forrrr chunk_sizer9 chunk_start chunk_end record_countr_get_offset_to_first_recordfirst_record_position)r<r2log_file_paramrrrrospathruse_sftpuse_event_viewerrpasswordretryerrordatas r#r=zBaseLogFileReader.__init__"s$ &#6  $(--d33 ;<<,-5 B73355 Bl66yAAG/5||N/K/Ku^^QWQ\Q\]dftQuQu  < & 8 H##%%11#' <.7 |2Gg,.fggg|2;N,.MNNN|2;H<.7 |2Gg,.fggg|2;N,.MNNN % 0 LtOaa b b b/@@UY@ZZHE  1$,2LdN`bj k k !%!3'   # EE=EFFF,??GGG EEEE  "3DDVY^D__$5dl6PRVRdfn$o$oDM%)]%7DNN+=EFFF,??GGG   0<.7 w(*vwww)$,8JKKDM!]/DNN  0 EHZZ [ [ [)$,8JKKDM!]/DNN RUYUgg h h h*4+=>>DM!]/DN$q$.:"=>>}&&q$/::%)%E%Ed%K%K"""s0.6H%% I+/2I&&I+ 6K L-K<<Lc"|j|jkS)zH If there is a previous chunk that can be read. )rrr@s r#rAzBaseLogFileReader.has_previouss$"<<:K:K:KTM]M]^^r/c6||jSrF) _format_sizerr@s r#rSzBaseLogFileReader.size_texts  000r/c|dkrdSd}t|D];\}}||dkr*d|||dz dz ||dz dfzcST^ + +I>T-?PP||~~r/cj|j|_|j|jz|_|SzL Returns a list with the records in the first chunk )rrrrrHr@s r#rOzBaseLogFileReader.firsts. 53doE||~~r/ct|j|j|jz |_|j|_|Sr)r9rrrrrrHr@s r#rQzBaseLogFileReader.lasts9t94>DO;[\\||~~r/cP|jjdkrdS|j|jjkS)NrT)r1rrrr@s r# file_changedzBaseLogFileReader.file_changeds) =  ) )4~!333r/c|jjdkrdS|jj}||jkr<||_t |j|j|jz |_|j|_dSdS)z Checks if the log file has been updated since it was opened and if so reopen the file again to keep going with the changes. Warning: this function only supports appending to the log file. rN) r1rrrr9rrrr)r<new_sizes r#r7zBaseLogFileReader.refresh%sl =  ) ) F=% t~ % %%DN"4#=t~PTP_?_``D !^DNNN & %r/N)T)rfrgrhrir=rArDrUrSrrrrrrHrJrMrOrQrr7r+r/r#rrs1  oLoLoLoLd=== /// ___111>>>" $$$8LLL ' ' '      444 , , , , ,r/rc4eZdZdZdfd ZdZfdZxZS)ErrorLogFileReaderzX This class enables the retrieval of log entries in a MySQL error log file. Tcd}d}d}d}d||||g} tj| tj} t t |||| ||d|jjdkrd |_ d |_ nd |_ tj| d ztj|_ d |_ dS)NzP^(?P(\d{2,4}-\d{1,2}-\d{2} {1,2}\d{1,2}:\d{2}:\d{2}) (\d+) \[(.*)\] (.*?))$z>^(?P(\d{6} {1,2}\d{1,2}:\d{2}:\d{2}) {1,2}([^ ]*) (.*?))$zR^(?P(\d{2})(\d{2})(\d{2}) {1,2}(\d{1,2}:\d{2}:\d{2}) ([a-zA-Z0-9_]*?) (.*?))$zU^(?P(\d{2,4}-\d{1,2}-\d{2}T{1,2}\d{1,2}:\d{2}:\d{2}.\d+Z) (\d+) \[(.*)\] (.*?))$|F)rr) Timestamprorud)Levelr)z Event messager}) timecreatedthreadidlevelmessage)r r)Typer)Detailsr}z|^(?P.+)$) rrecompileMrr r=r1rr3 column_keysrr) r<r2 file_namerrmysql_56mysql_55 mysql_pre55mysql_57 partial_rerrs r#r=zErrorLogFileReader.__init__;sfTk kXXx;IJJ jRT**  $''00)S*Viw|0}}} =  ) )!D  OD  !"D Jz,==rtDD r/c X|}|}|drt|ddS|drX|d}d|ddd|dd d|d dd |ddd |d |d gS|dr6d|dd|dd|dd |dd |d|dgS|dr2t |dd|dd|dzdz|dgSd d d |dgS)Nv56rCrv5520r*- roldr v57%F %T[]r) groupdictrrlstripr$)r<rgdictgrs r#rz"ErrorLogFileReader._extract_record\sT!! LLNN < '!A#<<  5\ '1BB')"1"vvvr!A#www1Q3ABBQSUWXYZW[]^_`]ab b 5\ ' ''(uuuaeeeQrUUUAbEEBB"qQSuU U 5\ '#AbE733QrUC!B%K#z-ErrorLogFileReader.current..ps&111qBw111111r/)rr rHrranyr)r<rdrecrs r#rHzErrorLogFileReader.currentks*D1199;; >DN * *"+C11CRC11111 #c"g,,.BKr/r T)rfrgrhrir=rrHrrs@r#r r 6spB ' ' '         r/r c*eZdZdZdfd ZdZxZS)GeneralLogFileReaderz` This class enables the retrieval of log entries in a MySQL general query log file. r Tctjdtj}tt||||||d|_d|_dS)Nz^(?P(\d{2,4}-\d{1,2}-\d{2}T{1,2}\d{1,2}:\d{2}:\d{2}.\d+Z)[\t ]*(\d+)\s*(.*?)(?:\t+| {2,})(.*?))$|^(?P(\d{6} {1,2}\d{1,2}:\d{2}:\d{2}[\t ]+|[\t ]+)(\s*\d+)(\s*.*?)(?:\t+| {2,})(.*?))$)r )rurv)rzrvr|r}r)rrrrrGr=r3r)r<r2rrrrrs r#r=zGeneralLogFileReader.__init__}slj]_a_cdd "D))227IsJXklll r/c|}|}|dr,t|dd|d|d|dgSt|ddS) Nr3rCr5r*rr)r&rr;rr$rr<rr=r>s r#rz$GeneralLogFileReader._extract_recordsg!! LLNN < !#AaD'22AaD!A$!E E!B$== r/rErfrgrhrir=rrrs@r#rGrGxsV      !!!!!!!r/rGc*eZdZdZdfd ZdZxZS)SlowLogFileReaderz] This class enables the retrieval of log entries in a MySQL slow query log file. r TFcd}d}tjd||gtj}t t |||||||d|_d|_dS)Nz(?:^|\n)(?P# Time: (\d{2,4}-\d{1,2}-\d{2}T{1,2}\d{1,2}:\d{2}:\d{2}.\d+Z).*?\n# User@Host: (.*?)\n# Query_time: +([0-9.]+) +Lock_time: +([\d.]+) +Rows_sent: +(\d+) +Rows_examined: +(\d+)\s*\n(.*?)(?=\n# |\n[^\n]+, Version: |$))z(?:^|\n)(?P# Time: (\d{6} {1,2}\d{1,2}:\d{2}:\d{2}).*?\n# User@Host: (.*?)\n# Query_time: +([0-9.]+) +Lock_time: +([\d.]+) +Rows_sent: +(\d+) +Rows_examined: +(\d+)\s*\n(.*?)(?=\n# |\n[^\n]+, Version: |$))r ))rro)z User@Hostrv)rrv)rrv)rrv)rrvrIr&) rrrSrrOr=r3r) r<r2rrrrr!rrrs r#r=zSlowLogFileReader.__init__s|~ij8X"677>> &&//CUhjuvvvr/c|}|}|dr/t|ddgt|ddzSt|ddS)Nr3rCr5r*r, rKrLs r#rz!SlowLogFileReader._extract_recordsh!! LLNN < "#AaD'223D1Q3LL@ @!C%>> !r/)r TFrMrs@r#rOrOsV """""""r/rO)rir workbench.logrrrwb_server_managementrrr wb_commonr r r workbench.utilsr rrrr$objectr&rkrrrr rGrOr+r/r#rZs5,JJX ::::::::::QQQQQQQQQQMMMMMMMMMM******    &]]]]]]]]@ Z Z Z Z Z. Z Z ZWWWWW+WWW*F2V,V,V,V,V,V,V,V,t>>>>>*>>>D!!!!!,!!!8""""")"""""r/