Repository: rueckstiess/mtools

Issue:
Replication log entries inappropriately displayed on mplotqueries
Newer versions of MongoDB include lines such as the following:

```
2018-05-01T21:57:45.989+0000 I REPL [replication-0] Scheduled new oplog query Fetcher source: host.name database: local query: { find: "oplog.rs", filter: { ts: { $gte: Timestamp(1525211859, 1) } }, tailable: true, oplogReplay: true, awaitData: true, maxTimeMS: 60000, batchSize: 13981010, term: 1, readConcern: { afterClusterTime: Timestamp(1525211859, 1) } } query metadata: { $replData: 1, $oplogQueryData: 1, $readPreference: { mode: "secondaryPreferred" } } active: 1 findNetworkTimeout: 65000ms getMoreNetworkTimeout: 7500ms shutting down?: 0 first: 1 firstCommandScheduler: RemoteCommandRetryScheduler request: RemoteCommand 16543 -- target:host.name db:local cmd:{ find: "oplog.rs", filter: { ts: { $gte: Timestamp(1525211859, 1) } }, tailable: true, oplogReplay: true, awaitData: true, maxTimeMS: 60000, batchSize: 13981010, term: 1, readConcern: { afterClusterTime: Timestamp(1525211859, 1) } } active: 1 callbackHandle.valid: 1 callbackHandle.cancelled: 0 attempt: 1 retryPolicy: RetryPolicyImpl maxAttempts: 1 maxTimeMillis: -1ms
```

It looks like the `-1ms` is getting picked up and interpreted as the duration of the operation.  It therefore shows up on the plot with the duration of `-1` milliseconds. 
 
### Expected behavior
`Scheduled new oplog query` log entries should not be plotted 


### Actual/current behavior
The entry gets plotted with the `maxTimeMillis` value.


### Steps to reproduce the actual/current behavior
Insert the line above into a file and run `mplotqueries` on it.


### Environment
<!--- Include relevant details for the environment you experienced the bug in -->

| Software         | Version
| ---------------- | -------
| mtools           | 1.4.1
| MongoDB server   | 3.6.4 
| Operating system | OS X 10.11.2


Comments:

Patch:
diff --git a/mtools/util/logevent.py b/mtools/util/logevent.py
index f9023de..7901e56 100644
--- a/mtools/util/logevent.py
+++ b/mtools/util/logevent.py
@@ -181,7 +181,10 @@ class LogEvent(object):
             # split_tokens = self.split_tokens
             line_str = self.line_str
 
-            if line_str and line_str.endswith('ms'):
+            if (line_str
+                and line_str.endswith('ms')
+                and 'Scheduled new oplog query' not in line_str):
+
                 try:
                     # find duration from end
                     space_pos = line_str.rfind(" ")


Test patch:
diff --git a/mtools/test/test_util_logevent.py b/mtools/test/test_util_logevent.py
index 7c4d68b..e0d93e1 100644
--- a/mtools/test/test_util_logevent.py
+++ b/mtools/test/test_util_logevent.py
@@ -63,6 +63,7 @@ line_truncated_24 = ("Wed Jan 28 00:31:16.302 [conn12345] warning: log line "
                      "reslen:256993 1445ms")
 line_fassert = ("***aborting after fassert() failure")
 line_empty = ("")
+line_new_oplog_query = ('2018-05-01T21:57:45.989+0000 I REPL [replication-0] Scheduled new oplog query Fetcher source: host.name database: local query: { find: "oplog.rs", filter: { ts: { $gte: Timestamp(1525211859, 1) } }, tailable: true, oplogReplay: true, awaitData: true, maxTimeMS: 60000, batchSize: 13981010, term: 1, readConcern: { afterClusterTime: Timestamp(1525211859, 1) } } query metadata: { $replData: 1, $oplogQueryData: 1, $readPreference: { mode: "secondaryPreferred" } } active: 1 findNetworkTimeout: 65000ms getMoreNetworkTimeout: 7500ms shutting down?: 0 first: 1 firstCommandScheduler: RemoteCommandRetryScheduler request: RemoteCommand 16543 -- target:host.name db:local cmd:{ find: "oplog.rs", filter: { ts: { $gte: Timestamp(1525211859, 1) } }, tailable: true, oplogReplay: true, awaitData: true, maxTimeMS: 60000, batchSize: 13981010, term: 1, readConcern: { afterClusterTime: Timestamp(1525211859, 1) } } active: 1 callbackHandle.valid: 1 callbackHandle.cancelled: 0 attempt: 1 retryPolicy: RetryPolicyImpl maxAttempts: 1 maxTimeMillis: -1ms')
 
 # fake system.profile documents
 profile_doc1 = {"op": "query", "ns": "test.foo",
@@ -252,6 +253,11 @@ def test_logevent_non_log_line():
     assert(le.nreturned == None)
     assert(le.pattern == None)
 
+def test_logevent_new_oplog_query():
+    """ Check that LogEvent correctly ignores new oplog query for duration extraction """
+    le = LogEvent(line_new_oplog_query)
+    assert(le.duration == None)
+
 def test_logevent_lazy_evaluation():
     """ Check that all LogEvent variables are evaluated lazily. """