1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/**
* Runs the $operationMetrics stage and ensures that all the expected fields are present.
*/
'use strict';
(function() {
load('jstests/libs/discover_topology.js'); // For Topology and DiscoverTopology.
if (typeof db === 'undefined') {
throw new Error(
"Expected mongo shell to be connected a server, but global 'db' object isn't defined");
}
// Disable implicit sessions so FSM workloads that kill random sessions won't interrupt the
// operations in this test that aren't resilient to interruptions.
TestData.disableImplicitSessions = true;
const topology = DiscoverTopology.findConnectedNodes(db.getMongo());
const aggregateMetricsBackground = function(host) {
function verifyFields(doc) {
const kTopLevelFields = [
"docBytesWritten",
"docUnitsWritten",
"idxEntryBytesWritten",
"idxEntryUnitsWritten",
"totalUnitsWritten",
"cpuNanos",
"db",
"primaryMetrics",
"secondaryMetrics"
];
const kReadFields = [
"docBytesRead",
"docUnitsRead",
"idxEntryBytesRead",
"idxEntryUnitsRead",
"keysSorted",
"docUnitsReturned"
];
for (let key of kTopLevelFields) {
assert(doc.hasOwnProperty(key), "The metrics output is missing the property: " + key);
}
let primaryMetrics = doc.primaryMetrics;
for (let key of kReadFields) {
assert(primaryMetrics.hasOwnProperty(key),
"The metrics output is missing the property: primaryMetrics." + key);
}
let secondaryMetrics = doc.secondaryMetrics;
for (let key of kReadFields) {
assert(secondaryMetrics.hasOwnProperty(key),
"The metrics output is missing the property: secondaryMetrics." + key);
}
}
let conn = new Mongo(host);
conn.setSecondaryOk();
assert.neq(
null, conn, "Failed to connect to host '" + host + "' for background metrics collection");
// Filter out arbiters.
if (conn.adminCommand({isMaster: 1}).arbiterOnly) {
print("Skipping background aggregation against test node: " + host +
" because it is an arbiter and has no data.");
return;
}
let db = conn.getDB("admin");
let clearMetrics = Math.random() < 0.9 ? false : true;
print("Running $operationMetrics with {clearMetrics: " + clearMetrics + "} on host: " + host);
const cursor = db.aggregate([{$operationMetrics: {clearMetrics: clearMetrics}}]);
while (cursor.hasNext()) {
let doc = cursor.next();
try {
verifyFields(doc);
} catch (e) {
print("caught exception while verifying that all expected fields are in the metrics " +
"output: " + tojson(doc));
throw (e);
}
}
};
// This file is run continuously and is very fast so we want to impose some kind of rate limiting
// which is why we sleep for 1 second here. This sleep is here rather than in
// aggregate_metrics_background.py because the background job that file uses is designed to be run
// continuously so it is easier and cleaner to just sleep here.
sleep(1000);
if (topology.type === Topology.kStandalone) {
try {
aggregateMetricsBackground(topology.mongod);
} catch (e) {
print("background aggregate metrics against the standalone failed");
throw e;
}
} else if (topology.type === Topology.kReplicaSet) {
for (let replicaMember of topology.nodes) {
try {
aggregateMetricsBackground(replicaMember);
} catch (e) {
print("background aggregate metrics was not successful against all replica set " +
"members");
throw e;
}
}
} else {
throw new Error("Unsupported topology configuration: " + tojson(topology));
}
})();
|