mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
dbtop
This commit is contained in:
parent
8356bec070
commit
166716bb25
6
db/db.h
6
db/db.h
@ -18,6 +18,7 @@
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../util/message.h"
|
||||
#include "../util/top.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
@ -76,6 +77,7 @@ namespace mongo {
|
||||
~dblock() {
|
||||
/* todo: this should be inlined */
|
||||
dbunlocking();
|
||||
Top::clientStop();
|
||||
}
|
||||
};
|
||||
|
||||
@ -129,7 +131,8 @@ namespace mongo {
|
||||
variables.
|
||||
*/
|
||||
assert( dbMutexInfo.isLocked() );
|
||||
|
||||
Top::clientStart( ns );
|
||||
|
||||
curNs = ns;
|
||||
string key = getKey( ns, path );
|
||||
map<string,Database*>::iterator it = databases.find(key);
|
||||
@ -191,6 +194,7 @@ namespace mongo {
|
||||
#else
|
||||
boost::detail::thread::lock_ops<boost::mutex>::unlock(dbMutex);
|
||||
#endif
|
||||
Top::clientStop();
|
||||
}
|
||||
~dbtemprelease() {
|
||||
#if BOOST_VERSION >= 103500
|
||||
|
@ -67,6 +67,7 @@ namespace mongo {
|
||||
{
|
||||
Timer lktm;
|
||||
dblock lk;
|
||||
Top::completeSnapshot();
|
||||
q = (q+1)%NStats;
|
||||
Timing timing;
|
||||
dbMutexInfo.timingInfo(timing.start, timing.timeLocked);
|
||||
@ -127,6 +128,14 @@ namespace mongo {
|
||||
if ( !seemCaughtUp ) ss << "</b>";
|
||||
ss << '\n';
|
||||
|
||||
ss << "\n<b>DBTOP</b>\n";
|
||||
ss << "<table border=1><tr align='left'><th>Namespace</th><th>%</th><th>Time</th>";
|
||||
vector< Top::Usage > usage;
|
||||
Top::usage( usage );
|
||||
for( vector< Top::Usage >::iterator i = usage.begin(); i != usage.end(); ++i )
|
||||
ss << setprecision( 2 ) << fixed << "<tr><td>" << i->ns << "</td><td>" << i->pct << "</td><td>" << i->time << "</td></tr>\n";
|
||||
ss << "</table>";
|
||||
|
||||
ss << "\n<b>dt\ttlocked</b>\n";
|
||||
unsigned i = q;
|
||||
while ( 1 ) {
|
||||
|
@ -650,5 +650,4 @@ namespace mongo {
|
||||
::exit(rc);
|
||||
}
|
||||
|
||||
|
||||
} // namespace mongo
|
||||
|
@ -127,5 +127,5 @@ namespace mongo {
|
||||
boost::thread_specific_ptr< AuthenticationInfo > backup_;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // namespace mongo
|
||||
|
1
stdafx.h
1
stdafx.h
@ -312,6 +312,7 @@ namespace mongo {
|
||||
#include <boost/archive/iterators/base64_from_binary.hpp>
|
||||
#include <boost/archive/iterators/binary_from_base64.hpp>
|
||||
#include <boost/archive/iterators/transform_width.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem/convenience.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
|
103
util/top.h
Normal file
103
util/top.h
Normal file
@ -0,0 +1,103 @@
|
||||
// top.h : DB usage monitor.
|
||||
//
|
||||
|
||||
/**
|
||||
* Copyright (C) 2009 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace mongo {
|
||||
|
||||
// No two functions of this class may be called concurrently.
|
||||
class Top {
|
||||
public:
|
||||
typedef boost::posix_time::ptime T;
|
||||
typedef boost::posix_time::time_duration D;
|
||||
static void clientStart( const char *client ) {
|
||||
clientStop();
|
||||
currentStart_ = currentTime();
|
||||
current_ = client;
|
||||
}
|
||||
static void clientStop() {
|
||||
if ( currentStart_ == T() )
|
||||
return;
|
||||
D d = currentTime() - currentStart_;
|
||||
size_t dot = current_.rfind( "." );
|
||||
if ( dot == string::npos || dot != current_.length() - 1 )
|
||||
recordUsage( current_, d );
|
||||
while( dot != string::npos ) {
|
||||
current_ = current_.substr( 0, dot );
|
||||
recordUsage( current_, d );
|
||||
dot = current_.rfind( "." );
|
||||
}
|
||||
currentStart_ = T();
|
||||
}
|
||||
struct Usage { string ns; D time; double pct; };
|
||||
static void usage( vector< Usage > &res ) {
|
||||
multimap< D, string, more > sorted;
|
||||
for( map< string, D >::iterator i = snapshot_.begin(); i != snapshot_.end(); ++i )
|
||||
sorted.insert( make_pair( i->second, i->first ) );
|
||||
set< string > already;
|
||||
for( multimap< D, string >::iterator i = sorted.begin(); i != sorted.end(); ++i ) {
|
||||
Usage u;
|
||||
already.insert( i->second );
|
||||
u.ns = i->second;
|
||||
u.time = totalUsage_[ u.ns ];
|
||||
u.pct = snapshotDuration_ != D() ? 100.0 * i->first.ticks() / snapshotDuration_.ticks() : 0;
|
||||
res.push_back( u );
|
||||
}
|
||||
for( map< string, D >::iterator i = totalUsage_.begin(); i != totalUsage_.end(); ++i ) {
|
||||
if ( already.count( i->first ) != 0 )
|
||||
continue;
|
||||
Usage u;
|
||||
u.ns = i->first;
|
||||
u.time = i->second;
|
||||
u.pct = 0;
|
||||
res.push_back( u );
|
||||
}
|
||||
}
|
||||
static void completeSnapshot() {
|
||||
if ( &snapshot_ == &snapshotA_ ) {
|
||||
snapshot_ = snapshotB_;
|
||||
nextSnapshot_ = snapshotA_;
|
||||
} else {
|
||||
snapshot_ = snapshotA_;
|
||||
nextSnapshot_ = snapshotB_;
|
||||
}
|
||||
snapshotDuration_ = currentTime() - snapshotStart_;
|
||||
snapshotStart_ = currentTime();
|
||||
nextSnapshot_.clear();
|
||||
}
|
||||
private:
|
||||
typedef map< string, D > UsageMap;
|
||||
static T currentTime() {
|
||||
return boost::posix_time::microsec_clock::universal_time();
|
||||
}
|
||||
static void recordUsage( const string &client, D duration ) {
|
||||
totalUsage_[ client ] += duration;
|
||||
nextSnapshot_[ client ] += duration;
|
||||
}
|
||||
struct more { bool operator()( const D &a, const D &b ) { return a > b; } };
|
||||
static string current_;
|
||||
static T currentStart_;
|
||||
static T snapshotStart_;
|
||||
static D snapshotDuration_;
|
||||
static UsageMap totalUsage_;
|
||||
static UsageMap snapshotA_;
|
||||
static UsageMap snapshotB_;
|
||||
static UsageMap &snapshot_;
|
||||
static UsageMap &nextSnapshot_;
|
||||
};
|
||||
|
||||
} // namespace mongo
|
@ -19,6 +19,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "goodies.h"
|
||||
#include "unittest.h"
|
||||
#include "top.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
@ -81,5 +82,15 @@ namespace mongo {
|
||||
|
||||
}
|
||||
} utilTest;
|
||||
|
||||
|
||||
string Top::current_;
|
||||
Top::T Top::currentStart_;
|
||||
Top::T Top::snapshotStart_ = Top::currentTime();
|
||||
Top::D Top::snapshotDuration_;
|
||||
Top::UsageMap Top::totalUsage_;
|
||||
Top::UsageMap Top::snapshotA_;
|
||||
Top::UsageMap Top::snapshotB_;
|
||||
Top::UsageMap &Top::snapshot_ = Top::snapshotA_;
|
||||
Top::UsageMap &Top::nextSnapshot_ = Top::snapshotB_;
|
||||
|
||||
} // namespace mongo
|
||||
|
Loading…
Reference in New Issue
Block a user