/**
* Copyright (C) 2008 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
#include "mongo/pch.h"
#include
#include
#include "mongo/db/json.h"
#include "mongo/tools/stat_util.h"
#include "mongo/tools/mongotop_options.h"
#include "mongo/tools/tool.h"
#include "mongo/util/options_parser/option_section.h"
namespace mongo {
class TopTool : public Tool {
public:
TopTool() : Tool() {
_autoreconnect = true;
}
virtual void printHelp( ostream & out ) {
printMongoTopHelp(&out);
}
NamespaceStats getData() {
if (mongoTopGlobalParams.useLocks)
return getDataLocks();
return getDataTop();
}
NamespaceStats getDataLocks() {
BSONObj out;
if (!conn().simpleCommand(toolGlobalParams.db, &out, "serverStatus")) {
toolError() << "error: " << out << std::endl;
return NamespaceStats();
}
return StatUtil::parseServerStatusLocks( out.getOwned() );
}
NamespaceStats getDataTop() {
NamespaceStats stats;
BSONObj out;
if (!conn().simpleCommand(toolGlobalParams.db, &out, "top")) {
toolError() << "error: " << out << std::endl;
return stats;
}
if ( ! out["totals"].isABSONObj() ) {
toolError() << "error: invalid top\n" << out << std::endl;
return stats;
}
out = out["totals"].Obj().getOwned();
BSONObjIterator i( out );
while ( i.more() ) {
BSONElement e = i.next();
if ( ! e.isABSONObj() )
continue;
NamespaceInfo& s = stats[e.fieldName()];
s.ns = e.fieldName();
s.read = e.Obj()["readLock"].Obj()["time"].numberLong() / 1000;
s.write = e.Obj()["writeLock"].Obj()["time"].numberLong() / 1000;
}
return stats;
}
void printDiff( const NamespaceStats& prev , const NamespaceStats& now ) {
if ( prev.size() == 0 || now.size() == 0 ) {
cout << "." << endl;
return;
}
vector data = StatUtil::computeDiff( prev , now );
unsigned longest = 30;
for ( unsigned i=0; i < data.size(); i++ ) {
const string& ns = data[i].ns;
if (!mongoTopGlobalParams.useLocks && ns.find('.') == string::npos)
continue;
if ( ns.size() > longest )
longest = ns.size();
}
int numberWidth = 10;
cout << "\n"
<< setw(longest) << (mongoTopGlobalParams.useLocks ? "db" : "ns")
<< setw(numberWidth+2) << "total"
<< setw(numberWidth+2) << "read"
<< setw(numberWidth+2) << "write"
<< "\t\t" << terseCurrentTime()
<< endl;
for ( int i=data.size()-1; i>=0 && data.size() - i < 10 ; i-- ) {
if (!mongoTopGlobalParams.useLocks && data[i].ns.find('.') == string::npos)
continue;
cout << setw(longest) << data[i].ns
<< setw(numberWidth) << setprecision(3) << data[i].total() << "ms"
<< setw(numberWidth) << setprecision(3) << data[i].read << "ms"
<< setw(numberWidth) << setprecision(3) << data[i].write << "ms"
<< endl;
}
}
int run() {
if (isMongos()) {
toolError() << "mongotop only works on instances of mongod." << std::endl;
return EXIT_FAILURE;
}
NamespaceStats prev = getData();
while ( true ) {
sleepsecs(mongoTopGlobalParams.sleep);
NamespaceStats now;
try {
now = getData();
}
catch ( std::exception& e ) {
toolError() << "can't get data: " << e.what() << std::endl;
continue;
}
if ( now.size() == 0 )
return -2;
try {
printDiff( prev , now );
}
catch ( AssertionException& e ) {
toolError() << "\nerror: " << e.what() << std::endl;
}
prev = now;
}
return 0;
}
};
REGISTER_MONGO_TOOL(TopTool);
}