summaryrefslogtreecommitdiff
path: root/src/mongo/util/procparser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/procparser.cpp')
-rw-r--r--src/mongo/util/procparser.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/mongo/util/procparser.cpp b/src/mongo/util/procparser.cpp
index 36f2ae0254e..af7a81fc7a2 100644
--- a/src/mongo/util/procparser.cpp
+++ b/src/mongo/util/procparser.cpp
@@ -406,6 +406,101 @@ Status parseProcMemInfoFile(StringData filename,
return parseProcMemInfo(keys, swString.getValue(), builder);
}
+//
+// Here is an example of the type of string it supports (long lines elided for clarity).
+// > cat /proc/net/netstat
+// TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed ...
+// TcpExt: 3437 5938 13368 ...
+// IpExt: InNoRoutes InTruncatedPkts InMcastPkts ...
+// IpExt: 999 1 4819969 ...
+//
+// Parser assumes file consists of alternating lines of keys and values
+// key and value lines consist of space-separated tokens
+// first token is a key prefix that is prepended in the output to each key
+// all prefixed keys and corresponding values are copied to output as-is
+//
+
+Status parseProcNetstat(const std::vector<StringData>& keys,
+ StringData data,
+ BSONObjBuilder* builder) {
+
+ using string_split_iterator = boost::split_iterator<StringData::const_iterator>;
+
+ string_split_iterator keysIt;
+ bool foundKeys = false;
+
+ // Split the file by lines.
+ uint32_t lineNum = 0;
+ for (string_split_iterator
+ lineIt = string_split_iterator(
+ data.begin(),
+ data.end(),
+ boost::token_finder([](char c) { return c == '\n'; }, boost::token_compress_on));
+ lineIt != string_split_iterator();
+ ++lineIt, ++lineNum) {
+
+ if (lineNum % 2 == 0) {
+
+ // even numbered lines are keys
+ keysIt = string_split_iterator(
+ (*lineIt).begin(),
+ (*lineIt).end(),
+ boost::token_finder([](char c) { return c == ' '; }, boost::token_compress_on));
+
+ } else {
+
+ // odd numbered lines are values
+ string_split_iterator valuesIt = string_split_iterator(
+ (*lineIt).begin(),
+ (*lineIt).end(),
+ boost::token_finder([](char c) { return c == ' '; }, boost::token_compress_on));
+
+ StringData prefix;
+
+ // iterate over the keys and values in parallel
+ for (uint32_t keyNum = 0;
+ keysIt != string_split_iterator() && valuesIt != string_split_iterator();
+ ++keysIt, ++valuesIt, ++keyNum) {
+
+ if (keyNum == 0) {
+
+ // first token is a prefix to be applied to remaining keys
+ prefix = StringData((*keysIt).begin(), (*keysIt).end());
+
+ // ignore line if prefix isn't in requested list
+ if (!keys.empty() && std::find(keys.begin(), keys.end(), prefix) == keys.end())
+ break;
+
+ } else {
+
+ // remaining tokens are key/value pairs
+ StringData key((*keysIt).begin(), (*keysIt).end());
+ StringData stringValue((*valuesIt).begin(), (*valuesIt).end());
+ uint64_t value;
+ if (parseNumberFromString(stringValue, &value).isOK()) {
+ builder->appendNumber(prefix.toString() + key.toString(), value);
+ foundKeys = true;
+ }
+ }
+ }
+ }
+ }
+
+ return foundKeys ? Status::OK()
+ : Status(ErrorCodes::NoSuchKey, "Failed to find any keys in netstats string");
+}
+
+Status parseProcNetstatFile(const std::vector<StringData>& keys,
+ StringData filename,
+ BSONObjBuilder* builder) {
+ auto swString = readFileAsString(filename);
+ if (!swString.isOK()) {
+ return swString.getStatus();
+ }
+ return parseProcNetstat(keys, swString.getValue(), builder);
+}
+
+
// Here is an example of the type of string it supports:
//
// For more information, see: