diff options
Diffstat (limited to 'src/mongo/util/procparser.cpp')
-rw-r--r-- | src/mongo/util/procparser.cpp | 95 |
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: |