-
Notifications
You must be signed in to change notification settings - Fork 405
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Added new flags for transaction in mloginfo and mlogfilter
- Loading branch information
1 parent
89ae6dc
commit f67fc8a
Showing
8 changed files
with
1,759 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import re | ||
|
||
from .base_filter import BaseFilter | ||
|
||
# SERVER-36461 - Filter to log slow transactions; Can be used in conjuncture with other filters | ||
|
||
|
||
class TransactionFilter(BaseFilter): | ||
filterArgs = [ | ||
('--transactions', {'action': 'store_true','default': False, | ||
'help': 'only output lines containing logs of transactions'}), | ||
] | ||
|
||
def __init__(self, mlogfilter): | ||
BaseFilter.__init__(self, mlogfilter) | ||
|
||
# set the keyword as transaction if the --transaction flag is set | ||
if self.mlogfilter.args['transactions']: | ||
self.words = "transaction" | ||
self.active = True | ||
else: | ||
self.active = False | ||
|
||
def accept(self, logevent): | ||
""" | ||
Process line. | ||
Overwrite BaseFilter.accept() and return True if the provided | ||
logevent contains keyword transaction, or False if not. | ||
""" | ||
|
||
if re.search(self.words, logevent.line_str): | ||
return True | ||
else: | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
# SERVER-36414 - Log information about slow transactions | ||
|
||
import re | ||
from collections import namedtuple | ||
from operator import itemgetter | ||
from mtools.util import OrderedDict | ||
from mtools.util.grouping import Grouping | ||
from mtools.util.print_table import print_table | ||
from .base_section import BaseSection | ||
|
||
|
||
LogTuple = namedtuple('LogTuple', ['datetime', 'txnNumber', 'autocommit', 'readConcern', | ||
'timeActiveMicros', 'timeInactiveMicros', 'duration']) | ||
|
||
|
||
def op_or_cmd(le): | ||
return le.operation if le.operation != 'command' else le.command | ||
|
||
|
||
class TransactionSection(BaseSection): | ||
"""TransactionSection class.""" | ||
|
||
name = "transactions" | ||
|
||
def __init__(self, mloginfo): | ||
BaseSection.__init__(self, mloginfo) | ||
|
||
# add --transactions flag to argparser | ||
helptext = 'outputs statistics about transactions' | ||
self.mloginfo.argparser_sectiongroup.add_argument('--transactions', | ||
action='store_true', | ||
help=helptext) | ||
|
||
# add --tsort flag to argparser for transaction sort | ||
self.mloginfo.argparser_sectiongroup.add_argument('--tsort', | ||
action='store', | ||
|
||
choices=['duration']) | ||
|
||
@property | ||
def active(self): | ||
"""Return boolean if this section is active.""" | ||
return self.mloginfo.args['transactions'] | ||
|
||
def run(self): | ||
|
||
"""Run this section and print out information.""" | ||
grouping = Grouping(group_by=lambda x: (x.datetime, x.txnNumber, | ||
x.autocommit, x.readConcern, x.timeActiveMicros, | ||
x.timeInactiveMicros, x.duration)) | ||
|
||
logfile = self.mloginfo.logfile | ||
|
||
if logfile.start and logfile.end: | ||
progress_start = self.mloginfo._datetime_to_epoch(logfile.start) | ||
progress_total = (self.mloginfo._datetime_to_epoch(logfile.end) - | ||
progress_start) | ||
else: | ||
self.mloginfo.progress_bar_enabled = False | ||
|
||
for i, le in enumerate(logfile): | ||
# update progress bar every 1000 lines | ||
|
||
if self.mloginfo.progress_bar_enabled and (i % 1000 == 0): | ||
if le.datetime: | ||
progress_curr = self.mloginfo._datetime_to_epoch(le.datetime) | ||
if progress_total: | ||
(self.mloginfo | ||
.update_progress(float(progress_curr - | ||
progress_start) / | ||
progress_total)) | ||
|
||
if re.search('transaction', le.line_str): | ||
lt = LogTuple(le.datetime, le.txnNumber, le.autocommit, le.readConcern, | ||
le.timeActiveMicros, le.timeInactiveMicros, le.duration) | ||
|
||
grouping.add(lt) | ||
|
||
grouping.sort_by_size() | ||
|
||
# clear progress bar again | ||
if self.mloginfo.progress_bar_enabled: | ||
self.mloginfo.update_progress(1.0) | ||
|
||
# no queries in the log file | ||
if not len(grouping): | ||
print('no transactions found.') | ||
return | ||
|
||
titles = ['datetime','txnNumber', 'autocommit', 'readConcern', 'timeActiveMicros', | ||
'timeInactiveMicros', 'duration'] | ||
|
||
table_rows = [] | ||
# using only important key-values | ||
# can be used in future | ||
for g in grouping: | ||
# calculate statistics for this group | ||
datetime, txnNumber, autocommit, readConcern, timeActiveMicros, timeInactiveMicros, duration = g | ||
stats = OrderedDict() | ||
stats['datetime'] = str(datetime) | ||
stats['txnNumber'] = txnNumber | ||
stats['autocommit'] = autocommit | ||
stats['readConcern'] = readConcern | ||
stats['timeActiveMicros'] = timeActiveMicros | ||
stats['timeInactiveMicros'] = timeInactiveMicros | ||
stats['duration'] = duration | ||
table_rows.append(stats) | ||
|
||
if self.mloginfo.args['tsort'] == 'duration': | ||
table_rows = sorted(table_rows, | ||
key=itemgetter(self.mloginfo.args['tsort']), | ||
reverse=True) | ||
|
||
print_table(table_rows, titles, uppercase_headers=True) | ||
|
||
print('') |
Oops, something went wrong.