diff options
Diffstat (limited to 'src/mongo/db/stats')
-rw-r--r-- | src/mongo/db/stats/counters.cpp | 196 | ||||
-rw-r--r-- | src/mongo/db/stats/counters.h | 114 | ||||
-rw-r--r-- | src/mongo/db/stats/fill_locker_info.cpp | 63 | ||||
-rw-r--r-- | src/mongo/db/stats/fill_locker_info.h | 10 | ||||
-rw-r--r-- | src/mongo/db/stats/fine_clock.h | 68 | ||||
-rw-r--r-- | src/mongo/db/stats/lock_server_status_section.cpp | 154 | ||||
-rw-r--r-- | src/mongo/db/stats/range_deleter_server_status.cpp | 109 | ||||
-rw-r--r-- | src/mongo/db/stats/snapshots.cpp | 124 | ||||
-rw-r--r-- | src/mongo/db/stats/snapshots.h | 136 | ||||
-rw-r--r-- | src/mongo/db/stats/snapshots_webplugins.cpp | 146 | ||||
-rw-r--r-- | src/mongo/db/stats/timer_stats.cpp | 67 | ||||
-rw-r--r-- | src/mongo/db/stats/timer_stats.h | 84 | ||||
-rw-r--r-- | src/mongo/db/stats/top.cpp | 188 | ||||
-rw-r--r-- | src/mongo/db/stats/top.h | 121 | ||||
-rw-r--r-- | src/mongo/db/stats/top_test.cpp | 10 |
15 files changed, 796 insertions, 794 deletions
diff --git a/src/mongo/db/stats/counters.cpp b/src/mongo/db/stats/counters.cpp index 51330b9d647..5b67e22dd6f 100644 --- a/src/mongo/db/stats/counters.cpp +++ b/src/mongo/db/stats/counters.cpp @@ -39,132 +39,134 @@ namespace mongo { - using std::endl; +using std::endl; - OpCounters::OpCounters() {} +OpCounters::OpCounters() {} - void OpCounters::incInsertInWriteLock(int n) { - RARELY _checkWrap(); - _insert.fetchAndAdd(n); - } +void OpCounters::incInsertInWriteLock(int n) { + RARELY _checkWrap(); + _insert.fetchAndAdd(n); +} - void OpCounters::gotInsert() { - RARELY _checkWrap(); - _insert.fetchAndAdd(1); - } +void OpCounters::gotInsert() { + RARELY _checkWrap(); + _insert.fetchAndAdd(1); +} - void OpCounters::gotQuery() { - RARELY _checkWrap(); - _query.fetchAndAdd(1); - } +void OpCounters::gotQuery() { + RARELY _checkWrap(); + _query.fetchAndAdd(1); +} - void OpCounters::gotUpdate() { - RARELY _checkWrap(); - _update.fetchAndAdd(1); - } +void OpCounters::gotUpdate() { + RARELY _checkWrap(); + _update.fetchAndAdd(1); +} - void OpCounters::gotDelete() { - RARELY _checkWrap(); - _delete.fetchAndAdd(1); - } +void OpCounters::gotDelete() { + RARELY _checkWrap(); + _delete.fetchAndAdd(1); +} - void OpCounters::gotGetMore() { - RARELY _checkWrap(); - _getmore.fetchAndAdd(1); - } +void OpCounters::gotGetMore() { + RARELY _checkWrap(); + _getmore.fetchAndAdd(1); +} - void OpCounters::gotCommand() { - RARELY _checkWrap(); - _command.fetchAndAdd(1); - } +void OpCounters::gotCommand() { + RARELY _checkWrap(); + _command.fetchAndAdd(1); +} - void OpCounters::gotOp( int op , bool isCommand ) { - switch ( op ) { - case dbInsert: /*gotInsert();*/ break; // need to handle multi-insert +void OpCounters::gotOp(int op, bool isCommand) { + switch (op) { + case dbInsert: /*gotInsert();*/ + break; // need to handle multi-insert case dbQuery: - if ( isCommand ) + if (isCommand) gotCommand(); else gotQuery(); break; - case dbUpdate: gotUpdate(); break; - case dbDelete: gotDelete(); break; - case dbGetMore: gotGetMore(); break; + case dbUpdate: + gotUpdate(); + break; + case dbDelete: + gotDelete(); + break; + case dbGetMore: + gotGetMore(); + break; case dbKillCursors: case opReply: case dbMsg: break; - default: log() << "OpCounters::gotOp unknown op: " << op << endl; - } + default: + log() << "OpCounters::gotOp unknown op: " << op << endl; } +} - void OpCounters::_checkWrap() { - const unsigned MAX = 1 << 30; - - bool wrap = - _insert.loadRelaxed() > MAX || - _query.loadRelaxed() > MAX || - _update.loadRelaxed() > MAX || - _delete.loadRelaxed() > MAX || - _getmore.loadRelaxed() > MAX || - _command.loadRelaxed() > MAX; - - if ( wrap ) { - _insert.store(0); - _query.store(0); - _update.store(0); - _delete.store(0); - _getmore.store(0); - _command.store(0); - } - } +void OpCounters::_checkWrap() { + const unsigned MAX = 1 << 30; - BSONObj OpCounters::getObj() const { - BSONObjBuilder b; - b.append( "insert" , _insert.loadRelaxed() ); - b.append( "query" , _query.loadRelaxed() ); - b.append( "update" , _update.loadRelaxed() ); - b.append( "delete" , _delete.loadRelaxed() ); - b.append( "getmore" , _getmore.loadRelaxed() ); - b.append( "command" , _command.loadRelaxed() ); - return b.obj(); - } + bool wrap = _insert.loadRelaxed() > MAX || _query.loadRelaxed() > MAX || + _update.loadRelaxed() > MAX || _delete.loadRelaxed() > MAX || + _getmore.loadRelaxed() > MAX || _command.loadRelaxed() > MAX; - void NetworkCounter::hit( long long bytesIn , long long bytesOut ) { - const long long MAX = 1ULL << 60; - - // don't care about the race as its just a counter - bool overflow = _bytesIn > MAX || _bytesOut > MAX; - - if ( overflow ) { - _lock.lock(); - _overflows++; - _bytesIn = bytesIn; - _bytesOut = bytesOut; - _requests = 1; - _lock.unlock(); - } - else { - _lock.lock(); - _bytesIn += bytesIn; - _bytesOut += bytesOut; - _requests++; - _lock.unlock(); - } + if (wrap) { + _insert.store(0); + _query.store(0); + _update.store(0); + _delete.store(0); + _getmore.store(0); + _command.store(0); } +} + +BSONObj OpCounters::getObj() const { + BSONObjBuilder b; + b.append("insert", _insert.loadRelaxed()); + b.append("query", _query.loadRelaxed()); + b.append("update", _update.loadRelaxed()); + b.append("delete", _delete.loadRelaxed()); + b.append("getmore", _getmore.loadRelaxed()); + b.append("command", _command.loadRelaxed()); + return b.obj(); +} + +void NetworkCounter::hit(long long bytesIn, long long bytesOut) { + const long long MAX = 1ULL << 60; - void NetworkCounter::append( BSONObjBuilder& b ) { + // don't care about the race as its just a counter + bool overflow = _bytesIn > MAX || _bytesOut > MAX; + + if (overflow) { _lock.lock(); - b.appendNumber( "bytesIn" , _bytesIn ); - b.appendNumber( "bytesOut" , _bytesOut ); - b.appendNumber( "numRequests" , _requests ); + _overflows++; + _bytesIn = bytesIn; + _bytesOut = bytesOut; + _requests = 1; + _lock.unlock(); + } else { + _lock.lock(); + _bytesIn += bytesIn; + _bytesOut += bytesOut; + _requests++; _lock.unlock(); } +} +void NetworkCounter::append(BSONObjBuilder& b) { + _lock.lock(); + b.appendNumber("bytesIn", _bytesIn); + b.appendNumber("bytesOut", _bytesOut); + b.appendNumber("numRequests", _requests); + _lock.unlock(); +} - OpCounters globalOpCounters; - OpCounters replOpCounters; - NetworkCounter networkCounter; +OpCounters globalOpCounters; +OpCounters replOpCounters; +NetworkCounter networkCounter; } diff --git a/src/mongo/db/stats/counters.h b/src/mongo/db/stats/counters.h index b29ebcce618..1821f7b7f1e 100644 --- a/src/mongo/db/stats/counters.h +++ b/src/mongo/db/stats/counters.h @@ -38,64 +38,76 @@ namespace mongo { - /** - * for storing operation counters - * note: not thread safe. ok with that for speed - */ - class OpCounters { - public: +/** + * for storing operation counters + * note: not thread safe. ok with that for speed + */ +class OpCounters { +public: + OpCounters(); + void incInsertInWriteLock(int n); + void gotInsert(); + void gotQuery(); + void gotUpdate(); + void gotDelete(); + void gotGetMore(); + void gotCommand(); + + void gotOp(int op, bool isCommand); + + BSONObj getObj() const; - OpCounters(); - void incInsertInWriteLock(int n); - void gotInsert(); - void gotQuery(); - void gotUpdate(); - void gotDelete(); - void gotGetMore(); - void gotCommand(); + // thse are used by snmp, and other things, do not remove + const AtomicUInt32* getInsert() const { + return &_insert; + } + const AtomicUInt32* getQuery() const { + return &_query; + } + const AtomicUInt32* getUpdate() const { + return &_update; + } + const AtomicUInt32* getDelete() const { + return &_delete; + } + const AtomicUInt32* getGetMore() const { + return &_getmore; + } + const AtomicUInt32* getCommand() const { + return &_command; + } - void gotOp( int op , bool isCommand ); +private: + void _checkWrap(); - BSONObj getObj() const; - - // thse are used by snmp, and other things, do not remove - const AtomicUInt32 * getInsert() const { return &_insert; } - const AtomicUInt32 * getQuery() const { return &_query; } - const AtomicUInt32 * getUpdate() const { return &_update; } - const AtomicUInt32 * getDelete() const { return &_delete; } - const AtomicUInt32 * getGetMore() const { return &_getmore; } - const AtomicUInt32 * getCommand() const { return &_command; } + // todo: there will be a lot of cache line contention on these. need to do something + // else eventually. + AtomicUInt32 _insert; + AtomicUInt32 _query; + AtomicUInt32 _update; + AtomicUInt32 _delete; + AtomicUInt32 _getmore; + AtomicUInt32 _command; +}; - private: - void _checkWrap(); - - // todo: there will be a lot of cache line contention on these. need to do something - // else eventually. - AtomicUInt32 _insert; - AtomicUInt32 _query; - AtomicUInt32 _update; - AtomicUInt32 _delete; - AtomicUInt32 _getmore; - AtomicUInt32 _command; - }; +extern OpCounters globalOpCounters; +extern OpCounters replOpCounters; - extern OpCounters globalOpCounters; - extern OpCounters replOpCounters; +class NetworkCounter { +public: + NetworkCounter() : _bytesIn(0), _bytesOut(0), _requests(0), _overflows(0) {} + void hit(long long bytesIn, long long bytesOut); + void append(BSONObjBuilder& b); - class NetworkCounter { - public: - NetworkCounter() : _bytesIn(0), _bytesOut(0), _requests(0), _overflows(0) {} - void hit( long long bytesIn , long long bytesOut ); - void append( BSONObjBuilder& b ); - private: - long long _bytesIn; - long long _bytesOut; - long long _requests; +private: + long long _bytesIn; + long long _bytesOut; + long long _requests; - long long _overflows; + long long _overflows; - SpinLock _lock; - }; + SpinLock _lock; +}; - extern NetworkCounter networkCounter; +extern NetworkCounter networkCounter; } diff --git a/src/mongo/db/stats/fill_locker_info.cpp b/src/mongo/db/stats/fill_locker_info.cpp index 028185f0f97..9541eb5de34 100644 --- a/src/mongo/db/stats/fill_locker_info.cpp +++ b/src/mongo/db/stats/fill_locker_info.cpp @@ -35,46 +35,45 @@ namespace mongo { - void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder) { - // "locks" section - BSONObjBuilder locks(infoBuilder.subobjStart("locks")); - const size_t locksSize = lockerInfo.locks.size(); +void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder) { + // "locks" section + BSONObjBuilder locks(infoBuilder.subobjStart("locks")); + const size_t locksSize = lockerInfo.locks.size(); - // Only add the last lock of each type, and use the largest mode encountered - LockMode modeForType[ResourceTypesCount] = { }; // default initialize to zero (min value) - for (size_t i = 0; i < locksSize; i++) { - const Locker::OneLock& lock = lockerInfo.locks[i]; - const ResourceType lockType = lock.resourceId.getType(); - const LockMode lockMode = std::max(lock.mode, modeForType[lockType]); + // Only add the last lock of each type, and use the largest mode encountered + LockMode modeForType[ResourceTypesCount] = {}; // default initialize to zero (min value) + for (size_t i = 0; i < locksSize; i++) { + const Locker::OneLock& lock = lockerInfo.locks[i]; + const ResourceType lockType = lock.resourceId.getType(); + const LockMode lockMode = std::max(lock.mode, modeForType[lockType]); - // Check that lockerInfo is sorted on resource type - invariant(i == 0 || lockType >= lockerInfo.locks[i - 1].resourceId.getType()); + // Check that lockerInfo is sorted on resource type + invariant(i == 0 || lockType >= lockerInfo.locks[i - 1].resourceId.getType()); - if (lock.resourceId == resourceIdLocalDB) { - locks.append("local", legacyModeName(lock.mode)); - continue; - } + if (lock.resourceId == resourceIdLocalDB) { + locks.append("local", legacyModeName(lock.mode)); + continue; + } - modeForType[lockType] = lockMode; + modeForType[lockType] = lockMode; - if (i + 1 < locksSize && lockerInfo.locks[i + 1].resourceId.getType() == lockType) { - continue; // skip this lock as it is not the last one of its type - } - else { - locks.append(resourceTypeName(lockType), legacyModeName(lockMode)); - } + if (i + 1 < locksSize && lockerInfo.locks[i + 1].resourceId.getType() == lockType) { + continue; // skip this lock as it is not the last one of its type + } else { + locks.append(resourceTypeName(lockType), legacyModeName(lockMode)); } - locks.done(); + } + locks.done(); - // "waitingForLock" section - infoBuilder.append("waitingForLock", lockerInfo.waitingResource.isValid()); + // "waitingForLock" section + infoBuilder.append("waitingForLock", lockerInfo.waitingResource.isValid()); - // "lockStats" section - { - BSONObjBuilder lockStats(infoBuilder.subobjStart("lockStats")); - lockerInfo.stats.report(&lockStats); - lockStats.done(); - } + // "lockStats" section + { + BSONObjBuilder lockStats(infoBuilder.subobjStart("lockStats")); + lockerInfo.stats.report(&lockStats); + lockStats.done(); } +} } // namespace mongo diff --git a/src/mongo/db/stats/fill_locker_info.h b/src/mongo/db/stats/fill_locker_info.h index 440b91b2816..03b99a2e371 100644 --- a/src/mongo/db/stats/fill_locker_info.h +++ b/src/mongo/db/stats/fill_locker_info.h @@ -32,10 +32,10 @@ namespace mongo { - /** - * Constructs a human-readable BSON from the specified LockerInfo structure. - * The lockerInfo must be sorted. - */ - void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder); +/** + * Constructs a human-readable BSON from the specified LockerInfo structure. + * The lockerInfo must be sorted. + */ +void fillLockerInfo(const Locker::LockerInfo& lockerInfo, BSONObjBuilder& infoBuilder); } // namespace mongo diff --git a/src/mongo/db/stats/fine_clock.h b/src/mongo/db/stats/fine_clock.h index 21f72d212a1..78762b73870 100644 --- a/src/mongo/db/stats/fine_clock.h +++ b/src/mongo/db/stats/fine_clock.h @@ -35,45 +35,41 @@ namespace mongo { - /** - * This is a nano-second precision clock. We're skipping the - * harware TSC in favor of clock_gettime() which in some systems - * does not involve a trip to the OS (VDSO). - * - * We're exporting a type WallTime that is and should remain - * opaque. The business of getting accurate time is still ongoing - * and we may change the internal representation of this class. - * (http://lwn.net/Articles/388188/) - * - * Really, you shouldn't be using this class in hot code paths for - * platforms you're not sure whether the overhead is low. - */ - class FineClock { - public: - - typedef timespec WallTime; +/** + * This is a nano-second precision clock. We're skipping the + * harware TSC in favor of clock_gettime() which in some systems + * does not involve a trip to the OS (VDSO). + * + * We're exporting a type WallTime that is and should remain + * opaque. The business of getting accurate time is still ongoing + * and we may change the internal representation of this class. + * (http://lwn.net/Articles/388188/) + * + * Really, you shouldn't be using this class in hot code paths for + * platforms you're not sure whether the overhead is low. + */ +class FineClock { +public: + typedef timespec WallTime; - static WallTime now() { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts; - } + static WallTime now() { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts; + } - static uint64_t diffInNanos( WallTime end, WallTime start ) { - uint64_t diff; - if ( end.tv_nsec < start.tv_nsec ) { - diff = 1000000000 * ( end.tv_sec - start.tv_sec - 1); - diff += 1000000000 + end.tv_nsec - start.tv_nsec; - } - else { - diff = 1000000000 * ( end.tv_sec - start.tv_sec ); - diff += end.tv_nsec - start.tv_nsec; - } - return diff; + static uint64_t diffInNanos(WallTime end, WallTime start) { + uint64_t diff; + if (end.tv_nsec < start.tv_nsec) { + diff = 1000000000 * (end.tv_sec - start.tv_sec - 1); + diff += 1000000000 + end.tv_nsec - start.tv_nsec; + } else { + diff = 1000000000 * (end.tv_sec - start.tv_sec); + diff += end.tv_nsec - start.tv_nsec; } - - }; + return diff; + } +}; } #endif // DB_STATS_FINE_CLOCK_HEADER - diff --git a/src/mongo/db/stats/lock_server_status_section.cpp b/src/mongo/db/stats/lock_server_status_section.cpp index c8d583d403e..e320fe04930 100644 --- a/src/mongo/db/stats/lock_server_status_section.cpp +++ b/src/mongo/db/stats/lock_server_status_section.cpp @@ -37,103 +37,103 @@ namespace mongo { namespace { - class GlobalLockServerStatusSection : public ServerStatusSection { - public: - GlobalLockServerStatusSection() : ServerStatusSection("globalLock") { - _started = curTimeMillis64(); - } - - virtual bool includeByDefault() const { return true; } - - virtual BSONObj generateSection(OperationContext* txn, - const BSONElement& configElement) const { - - int numTotal = 0; - int numWriteLocked = 0; - int numReadLocked = 0; - int numWaitingRead = 0; - int numWaitingWrite = 0; - - // This returns the blocked lock states - for (ServiceContext::LockedClientsCursor cursor(txn->getClient()->getServiceContext()); - Client* client = cursor.next();) { - - invariant(client); - ++numTotal; - stdx::unique_lock<Client> uniqueLock(*client); - - const OperationContext* opCtx = client->getOperationContext(); - if (opCtx == NULL) continue; - - if (opCtx->lockState()->isWriteLocked()) { - numWriteLocked++; - - if (opCtx->lockState()->getWaitingResource().isValid()) { - numWaitingWrite++; - } +class GlobalLockServerStatusSection : public ServerStatusSection { +public: + GlobalLockServerStatusSection() : ServerStatusSection("globalLock") { + _started = curTimeMillis64(); + } + + virtual bool includeByDefault() const { + return true; + } + + virtual BSONObj generateSection(OperationContext* txn, const BSONElement& configElement) const { + int numTotal = 0; + int numWriteLocked = 0; + int numReadLocked = 0; + int numWaitingRead = 0; + int numWaitingWrite = 0; + + // This returns the blocked lock states + for (ServiceContext::LockedClientsCursor cursor(txn->getClient()->getServiceContext()); + Client* client = cursor.next();) { + invariant(client); + ++numTotal; + stdx::unique_lock<Client> uniqueLock(*client); + + const OperationContext* opCtx = client->getOperationContext(); + if (opCtx == NULL) + continue; + + if (opCtx->lockState()->isWriteLocked()) { + numWriteLocked++; + + if (opCtx->lockState()->getWaitingResource().isValid()) { + numWaitingWrite++; } - else if (opCtx->lockState()->isReadLocked()) { - numReadLocked++; + } else if (opCtx->lockState()->isReadLocked()) { + numReadLocked++; - if (opCtx->lockState()->getWaitingResource().isValid()) { - numWaitingRead++; - } + if (opCtx->lockState()->getWaitingResource().isValid()) { + numWaitingRead++; } } + } - // Construct the actual return value out of the mutex - BSONObjBuilder ret; + // Construct the actual return value out of the mutex + BSONObjBuilder ret; - ret.append("totalTime", (long long)(1000 * (curTimeMillis64() - _started))); + ret.append("totalTime", (long long)(1000 * (curTimeMillis64() - _started))); - { - BSONObjBuilder currentQueueBuilder(ret.subobjStart("currentQueue")); + { + BSONObjBuilder currentQueueBuilder(ret.subobjStart("currentQueue")); - currentQueueBuilder.append("total", numWaitingRead + numWaitingWrite); - currentQueueBuilder.append("readers", numWaitingRead); - currentQueueBuilder.append("writers", numWaitingWrite); - currentQueueBuilder.done(); - } + currentQueueBuilder.append("total", numWaitingRead + numWaitingWrite); + currentQueueBuilder.append("readers", numWaitingRead); + currentQueueBuilder.append("writers", numWaitingWrite); + currentQueueBuilder.done(); + } - { - BSONObjBuilder activeClientsBuilder(ret.subobjStart("activeClients")); + { + BSONObjBuilder activeClientsBuilder(ret.subobjStart("activeClients")); - activeClientsBuilder.append("total", numTotal); - activeClientsBuilder.append("readers", numReadLocked); - activeClientsBuilder.append("writers", numWriteLocked); - activeClientsBuilder.done(); - } + activeClientsBuilder.append("total", numTotal); + activeClientsBuilder.append("readers", numReadLocked); + activeClientsBuilder.append("writers", numWriteLocked); + activeClientsBuilder.done(); + } - ret.done(); + ret.done(); - return ret.obj(); - } + return ret.obj(); + } - private: - unsigned long long _started; +private: + unsigned long long _started; - } globalLockServerStatusSection; +} globalLockServerStatusSection; - class LockStatsServerStatusSection : public ServerStatusSection { - public: - LockStatsServerStatusSection() : ServerStatusSection("locks") { } +class LockStatsServerStatusSection : public ServerStatusSection { +public: + LockStatsServerStatusSection() : ServerStatusSection("locks") {} - virtual bool includeByDefault() const { return true; } + virtual bool includeByDefault() const { + return true; + } - virtual BSONObj generateSection(OperationContext* txn, - const BSONElement& configElement) const { - BSONObjBuilder ret; + virtual BSONObj generateSection(OperationContext* txn, const BSONElement& configElement) const { + BSONObjBuilder ret; - SingleThreadedLockStats stats; - reportGlobalLockingStats(&stats); + SingleThreadedLockStats stats; + reportGlobalLockingStats(&stats); - stats.report(&ret); + stats.report(&ret); - return ret.obj(); - } + return ret.obj(); + } - } lockStatsServerStatusSection; +} lockStatsServerStatusSection; -} // namespace -} // namespace mongo +} // namespace +} // namespace mongo diff --git a/src/mongo/db/stats/range_deleter_server_status.cpp b/src/mongo/db/stats/range_deleter_server_status.cpp index e625e16f01b..817ffa444e4 100644 --- a/src/mongo/db/stats/range_deleter_server_status.cpp +++ b/src/mongo/db/stats/range_deleter_server_status.cpp @@ -32,69 +32,70 @@ namespace mongo { - /** - * Server status section for RangeDeleter. - * - * Sample format: - * - * rangeDeleter: { - * lastDeleteStats: [ - * { - * deleteDocs: NumberLong(5); - * queueStart: ISODate("2014-06-11T22:45:30.221Z"), - * queueEnd: ISODate("2014-06-11T22:45:30.221Z"), - * deleteStart: ISODate("2014-06-11T22:45:30.221Z"), - * deleteEnd: ISODate("2014-06-11T22:45:30.221Z"), - * waitForReplStart: ISODate("2014-06-11T22:45:30.221Z"), - * waitForReplEnd: ISODate("2014-06-11T22:45:30.221Z") - * } - * ] - * } - */ - class RangeDeleterServerStatusSection : public ServerStatusSection { - public: - RangeDeleterServerStatusSection() : ServerStatusSection( "rangeDeleter" ){} - bool includeByDefault() const { return false; } - - BSONObj generateSection(OperationContext* txn, - const BSONElement& configElement) const { +/** + * Server status section for RangeDeleter. + * + * Sample format: + * + * rangeDeleter: { + * lastDeleteStats: [ + * { + * deleteDocs: NumberLong(5); + * queueStart: ISODate("2014-06-11T22:45:30.221Z"), + * queueEnd: ISODate("2014-06-11T22:45:30.221Z"), + * deleteStart: ISODate("2014-06-11T22:45:30.221Z"), + * deleteEnd: ISODate("2014-06-11T22:45:30.221Z"), + * waitForReplStart: ISODate("2014-06-11T22:45:30.221Z"), + * waitForReplEnd: ISODate("2014-06-11T22:45:30.221Z") + * } + * ] + * } + */ +class RangeDeleterServerStatusSection : public ServerStatusSection { +public: + RangeDeleterServerStatusSection() : ServerStatusSection("rangeDeleter") {} + bool includeByDefault() const { + return false; + } - RangeDeleter* deleter = getDeleter(); - if (!deleter) { - return BSONObj(); - } + BSONObj generateSection(OperationContext* txn, const BSONElement& configElement) const { + RangeDeleter* deleter = getDeleter(); + if (!deleter) { + return BSONObj(); + } - BSONObjBuilder result; + BSONObjBuilder result; - OwnedPointerVector<DeleteJobStats> statsList; - deleter->getStatsHistory(&statsList.mutableVector()); - BSONArrayBuilder oldStatsBuilder; - for (OwnedPointerVector<DeleteJobStats>::const_iterator it = statsList.begin(); - it != statsList.end(); ++it) { - BSONObjBuilder entryBuilder; - entryBuilder.append("deletedDocs", (*it)->deletedDocCount); + OwnedPointerVector<DeleteJobStats> statsList; + deleter->getStatsHistory(&statsList.mutableVector()); + BSONArrayBuilder oldStatsBuilder; + for (OwnedPointerVector<DeleteJobStats>::const_iterator it = statsList.begin(); + it != statsList.end(); + ++it) { + BSONObjBuilder entryBuilder; + entryBuilder.append("deletedDocs", (*it)->deletedDocCount); - if ((*it)->queueEndTS > Date_t()) { - entryBuilder.append("queueStart", (*it)->queueStartTS); - entryBuilder.append("queueEnd", (*it)->queueEndTS); - } + if ((*it)->queueEndTS > Date_t()) { + entryBuilder.append("queueStart", (*it)->queueStartTS); + entryBuilder.append("queueEnd", (*it)->queueEndTS); + } - if ((*it)->deleteEndTS > Date_t()) { - entryBuilder.append("deleteStart", (*it)->deleteStartTS); - entryBuilder.append("deleteEnd", (*it)->deleteEndTS); + if ((*it)->deleteEndTS > Date_t()) { + entryBuilder.append("deleteStart", (*it)->deleteStartTS); + entryBuilder.append("deleteEnd", (*it)->deleteEndTS); - if ((*it)->waitForReplEndTS > Date_t()) { - entryBuilder.append("waitForReplStart", (*it)->waitForReplStartTS); - entryBuilder.append("waitForReplEnd", (*it)->waitForReplEndTS); - } + if ((*it)->waitForReplEndTS > Date_t()) { + entryBuilder.append("waitForReplStart", (*it)->waitForReplStartTS); + entryBuilder.append("waitForReplEnd", (*it)->waitForReplEndTS); } - - oldStatsBuilder.append(entryBuilder.obj()); } - result.append("lastDeleteStats", oldStatsBuilder.arr()); - return result.obj(); + oldStatsBuilder.append(entryBuilder.obj()); } + result.append("lastDeleteStats", oldStatsBuilder.arr()); + + return result.obj(); + } - } rangeDeleterServerStatusSection; +} rangeDeleterServerStatusSection; } diff --git a/src/mongo/db/stats/snapshots.cpp b/src/mongo/db/stats/snapshots.cpp index 80b5a66c98f..ce14714b87d 100644 --- a/src/mongo/db/stats/snapshots.cpp +++ b/src/mongo/db/stats/snapshots.cpp @@ -45,83 +45,77 @@ */ namespace mongo { - using std::unique_ptr; - using std::endl; +using std::unique_ptr; +using std::endl; - void SnapshotData::takeSnapshot() { - _created = curTimeMicros64(); - Top::get(getGlobalServiceContext()).cloneMap(_usage); - } +void SnapshotData::takeSnapshot() { + _created = curTimeMicros64(); + Top::get(getGlobalServiceContext()).cloneMap(_usage); +} - SnapshotDelta::SnapshotDelta( const SnapshotData& older , const SnapshotData& newer ) - : _older( older ) , _newer( newer ) { - verify( _newer._created > _older._created ); - _elapsed = _newer._created - _older._created; - } +SnapshotDelta::SnapshotDelta(const SnapshotData& older, const SnapshotData& newer) + : _older(older), _newer(newer) { + verify(_newer._created > _older._created); + _elapsed = _newer._created - _older._created; +} - Top::UsageMap SnapshotDelta::collectionUsageDiff() { - verify( _newer._created > _older._created ); - Top::UsageMap u; - - for ( Top::UsageMap::const_iterator i=_newer._usage.begin(); - i != _newer._usage.end(); ++i ) { - Top::UsageMap::const_iterator j = _older._usage.find(i->first); - if (j != _older._usage.end()) - u[i->first] = Top::CollectionData( j->second , i->second ); - else - u[i->first] = i->second; - } - return u; - } +Top::UsageMap SnapshotDelta::collectionUsageDiff() { + verify(_newer._created > _older._created); + Top::UsageMap u; - Snapshots::Snapshots() - : _loc(0) - , _stored(0) - {} - - const SnapshotData* Snapshots::takeSnapshot() { - stdx::lock_guard<stdx::mutex> lk(_lock); - _loc = ( _loc + 1 ) % kNumSnapshots; - _snapshots[_loc].takeSnapshot(); - if ( _stored < kNumSnapshots ) - _stored++; - return &_snapshots[_loc]; + for (Top::UsageMap::const_iterator i = _newer._usage.begin(); i != _newer._usage.end(); ++i) { + Top::UsageMap::const_iterator j = _older._usage.find(i->first); + if (j != _older._usage.end()) + u[i->first] = Top::CollectionData(j->second, i->second); + else + u[i->first] = i->second; } + return u; +} - StatusWith<SnapshotDiff> Snapshots::computeDelta() { - stdx::lock_guard<stdx::mutex> lk(_lock); - - // We need 2 snapshots to calculate a delta - if (_stored < 2) { - return StatusWith<SnapshotDiff>(ErrorCodes::BadValue, - "Less than 2 snapshots exist"); - } +Snapshots::Snapshots() : _loc(0), _stored(0) {} - // The following logic depends on there being exactly 2 stored snapshots - BOOST_STATIC_ASSERT(kNumSnapshots == 2); +const SnapshotData* Snapshots::takeSnapshot() { + stdx::lock_guard<stdx::mutex> lk(_lock); + _loc = (_loc + 1) % kNumSnapshots; + _snapshots[_loc].takeSnapshot(); + if (_stored < kNumSnapshots) + _stored++; + return &_snapshots[_loc]; +} - // Current and previous napshot alternates between indexes 0 and 1 - int currIdx = _loc; - int prevIdx = _loc > 0 ? 0 : 1; - SnapshotDelta delta(_snapshots[prevIdx], _snapshots[currIdx]); +StatusWith<SnapshotDiff> Snapshots::computeDelta() { + stdx::lock_guard<stdx::mutex> lk(_lock); - return SnapshotDiff(delta.collectionUsageDiff(), delta.elapsed()); + // We need 2 snapshots to calculate a delta + if (_stored < 2) { + return StatusWith<SnapshotDiff>(ErrorCodes::BadValue, "Less than 2 snapshots exist"); } - void SnapshotThread::run() { - Client::initThread("snapshot"); - while ( ! inShutdown() ) { - try { - statsSnapshots.takeSnapshot(); - } - catch ( std::exception& e ) { - log() << "ERROR in SnapshotThread: " << e.what() << endl; - } - - sleepsecs(4); + // The following logic depends on there being exactly 2 stored snapshots + BOOST_STATIC_ASSERT(kNumSnapshots == 2); + + // Current and previous napshot alternates between indexes 0 and 1 + int currIdx = _loc; + int prevIdx = _loc > 0 ? 0 : 1; + SnapshotDelta delta(_snapshots[prevIdx], _snapshots[currIdx]); + + return SnapshotDiff(delta.collectionUsageDiff(), delta.elapsed()); +} + +void SnapshotThread::run() { + Client::initThread("snapshot"); + while (!inShutdown()) { + try { + statsSnapshots.takeSnapshot(); + } catch (std::exception& e) { + log() << "ERROR in SnapshotThread: " << e.what() << endl; } + + sleepsecs(4); } +} - Snapshots statsSnapshots; - SnapshotThread snapshotThread; +Snapshots statsSnapshots; +SnapshotThread snapshotThread; } diff --git a/src/mongo/db/stats/snapshots.h b/src/mongo/db/stats/snapshots.h index 6f3b90e0cb9..f9f47d661d1 100644 --- a/src/mongo/db/stats/snapshots.h +++ b/src/mongo/db/stats/snapshots.h @@ -41,76 +41,76 @@ */ namespace mongo { - class SnapshotThread; +class SnapshotThread; - /** - * stores a point in time snapshot - * i.e. all counters at a given time - */ - class SnapshotData { - void takeSnapshot(); - - unsigned long long _created; - Top::UsageMap _usage; - - friend class SnapshotThread; - friend class SnapshotDelta; - friend class Snapshots; - }; - - /** - * contains performance information for a time period - */ - class SnapshotDelta { - public: - SnapshotDelta( const SnapshotData& older , const SnapshotData& newer ); - - unsigned long long elapsed() const { - return _elapsed; - } - - Top::UsageMap collectionUsageDiff(); - - private: - const SnapshotData& _older; - const SnapshotData& _newer; - - unsigned long long _elapsed; - }; - - struct SnapshotDiff { - Top::UsageMap usageDiff; - unsigned long long timeElapsed; - - SnapshotDiff() = default; - SnapshotDiff(Top::UsageMap map, unsigned long long elapsed) - : usageDiff(std::move(map)), timeElapsed(elapsed) {} - }; - - class Snapshots { - public: - Snapshots(); - - const SnapshotData* takeSnapshot(); - - StatusWith<SnapshotDiff> computeDelta(); - - private: - stdx::mutex _lock; - static const int kNumSnapshots = 2; - SnapshotData _snapshots[kNumSnapshots]; - int _loc; - int _stored; - }; - - class SnapshotThread : public BackgroundJob { - public: - virtual std::string name() const { return "snapshot"; } - void run(); - }; +/** + * stores a point in time snapshot + * i.e. all counters at a given time + */ +class SnapshotData { + void takeSnapshot(); - extern Snapshots statsSnapshots; - extern SnapshotThread snapshotThread; + unsigned long long _created; + Top::UsageMap _usage; + friend class SnapshotThread; + friend class SnapshotDelta; + friend class Snapshots; +}; +/** + * contains performance information for a time period + */ +class SnapshotDelta { +public: + SnapshotDelta(const SnapshotData& older, const SnapshotData& newer); + + unsigned long long elapsed() const { + return _elapsed; + } + + Top::UsageMap collectionUsageDiff(); + +private: + const SnapshotData& _older; + const SnapshotData& _newer; + + unsigned long long _elapsed; +}; + +struct SnapshotDiff { + Top::UsageMap usageDiff; + unsigned long long timeElapsed; + + SnapshotDiff() = default; + SnapshotDiff(Top::UsageMap map, unsigned long long elapsed) + : usageDiff(std::move(map)), timeElapsed(elapsed) {} +}; + +class Snapshots { +public: + Snapshots(); + + const SnapshotData* takeSnapshot(); + + StatusWith<SnapshotDiff> computeDelta(); + +private: + stdx::mutex _lock; + static const int kNumSnapshots = 2; + SnapshotData _snapshots[kNumSnapshots]; + int _loc; + int _stored; +}; + +class SnapshotThread : public BackgroundJob { +public: + virtual std::string name() const { + return "snapshot"; + } + void run(); +}; + +extern Snapshots statsSnapshots; +extern SnapshotThread snapshotThread; } diff --git a/src/mongo/db/stats/snapshots_webplugins.cpp b/src/mongo/db/stats/snapshots_webplugins.cpp index cc604c6e983..8690935866a 100644 --- a/src/mongo/db/stats/snapshots_webplugins.cpp +++ b/src/mongo/db/stats/snapshots_webplugins.cpp @@ -36,81 +36,83 @@ namespace mongo { namespace { - using namespace html; - - using std::fixed; - using std::setprecision; - using std::string; - using std::stringstream; - - class DBTopStatus : public WebStatusPlugin { - public: - DBTopStatus() : WebStatusPlugin( "dbtop" , 50 , "(occurrences|percent of elapsed)" ) {} - - void display( stringstream& ss , double elapsed , const Top::UsageData& usage ) { - ss << "<td>"; - ss << usage.count; - ss << "</td><td>"; - double per = 100 * ((double)usage.time)/elapsed; - if( per == (int) per ) - ss << (int) per; - else - ss << setprecision(1) << fixed << per; - ss << '%'; - ss << "</td>"; +using namespace html; + +using std::fixed; +using std::setprecision; +using std::string; +using std::stringstream; + +class DBTopStatus : public WebStatusPlugin { +public: + DBTopStatus() : WebStatusPlugin("dbtop", 50, "(occurrences|percent of elapsed)") {} + + void display(stringstream& ss, double elapsed, const Top::UsageData& usage) { + ss << "<td>"; + ss << usage.count; + ss << "</td><td>"; + double per = 100 * ((double)usage.time) / elapsed; + if (per == (int)per) + ss << (int)per; + else + ss << setprecision(1) << fixed << per; + ss << '%'; + ss << "</td>"; + } + + void display(stringstream& ss, + double elapsed, + const string& ns, + const Top::CollectionData& data) { + if (ns != "TOTAL" && data.total.count == 0) + return; + ss << "<tr><th>" << html::escape(ns) << "</th>"; + + display(ss, elapsed, data.total); + + display(ss, elapsed, data.readLock); + display(ss, elapsed, data.writeLock); + + display(ss, elapsed, data.queries); + display(ss, elapsed, data.getmore); + display(ss, elapsed, data.insert); + display(ss, elapsed, data.update); + display(ss, elapsed, data.remove); + + ss << "</tr>\n"; + } + + void run(OperationContext* txn, stringstream& ss) { + StatusWith<SnapshotDiff> diff = statsSnapshots.computeDelta(); + + if (!diff.isOK()) + return; + + ss << "<table border=1 cellpadding=2 cellspacing=0>"; + ss << "<tr align='left'><th>"; + ss << a("http://dochub.mongodb.org/core/whatisanamespace", "namespace") + << "NS</a></th>" + "<th colspan=2>total</th>" + "<th colspan=2>Reads</th>" + "<th colspan=2>Writes</th>" + "<th colspan=2>Queries</th>" + "<th colspan=2>GetMores</th>" + "<th colspan=2>Inserts</th>" + "<th colspan=2>Updates</th>" + "<th colspan=2>Removes</th>"; + ss << "</tr>\n"; + + const Top::UsageMap& usage = diff.getValue().usageDiff; + unsigned long long elapsed = diff.getValue().timeElapsed; + for (Top::UsageMap::const_iterator i = usage.begin(); i != usage.end(); ++i) { + display(ss, (double)elapsed, i->first, i->second); } - void display( stringstream& ss , double elapsed , const string& ns , const Top::CollectionData& data ) { - if ( ns != "TOTAL" && data.total.count == 0 ) - return; - ss << "<tr><th>" << html::escape( ns ) << "</th>"; + ss << "</table>"; + } - display( ss , elapsed , data.total ); - - display( ss , elapsed , data.readLock ); - display( ss , elapsed , data.writeLock ); - - display( ss , elapsed , data.queries ); - display( ss , elapsed , data.getmore ); - display( ss , elapsed , data.insert ); - display( ss , elapsed , data.update ); - display( ss , elapsed , data.remove ); - - ss << "</tr>\n"; - } - - void run(OperationContext* txn, stringstream& ss) { - StatusWith<SnapshotDiff> diff = statsSnapshots.computeDelta(); - - if ( ! diff.isOK() ) - return; - - ss << "<table border=1 cellpadding=2 cellspacing=0>"; - ss << "<tr align='left'><th>"; - ss << a("http://dochub.mongodb.org/core/whatisanamespace", "namespace") << - "NS</a></th>" - "<th colspan=2>total</th>" - "<th colspan=2>Reads</th>" - "<th colspan=2>Writes</th>" - "<th colspan=2>Queries</th>" - "<th colspan=2>GetMores</th>" - "<th colspan=2>Inserts</th>" - "<th colspan=2>Updates</th>" - "<th colspan=2>Removes</th>"; - ss << "</tr>\n"; - - const Top::UsageMap& usage = diff.getValue().usageDiff; - unsigned long long elapsed = diff.getValue().timeElapsed; - for ( Top::UsageMap::const_iterator i=usage.begin(); i != usage.end(); ++i ) { - display( ss , (double) elapsed , i->first , i->second ); - } - - ss << "</table>"; - - } - - virtual void init() {} - } dbtopStatus; + virtual void init() {} +} dbtopStatus; } // namespace } // namespace mongo diff --git a/src/mongo/db/stats/timer_stats.cpp b/src/mongo/db/stats/timer_stats.cpp index 728f05cb3f3..1030d296eb4 100644 --- a/src/mongo/db/stats/timer_stats.cpp +++ b/src/mongo/db/stats/timer_stats.cpp @@ -31,47 +31,44 @@ namespace mongo { - TimerHolder::TimerHolder( TimerStats* stats ) - : _stats( stats ), _recorded( false ){ - } - - TimerHolder::~TimerHolder() { - if ( ! _recorded ) { - recordMillis(); - } - } +TimerHolder::TimerHolder(TimerStats* stats) : _stats(stats), _recorded(false) {} - int TimerHolder::recordMillis() { - _recorded = true; - if ( _stats ) { - return _stats->record( _t ); - } - return _t.millis(); +TimerHolder::~TimerHolder() { + if (!_recorded) { + recordMillis(); } +} - void TimerStats::recordMillis( int millis ) { - scoped_spinlock lk( _lock ); - _num++; - _totalMillis += millis; +int TimerHolder::recordMillis() { + _recorded = true; + if (_stats) { + return _stats->record(_t); } + return _t.millis(); +} - int TimerStats::record( const Timer& timer ) { - int millis = timer.millis(); - recordMillis( millis ); - return millis; - } +void TimerStats::recordMillis(int millis) { + scoped_spinlock lk(_lock); + _num++; + _totalMillis += millis; +} - BSONObj TimerStats::getReport() const { - long long n, t; - { - scoped_spinlock lk( _lock ); - n = _num; - t = _totalMillis; - } - BSONObjBuilder b(64); - b.appendNumber( "num", n ); - b.appendNumber( "totalMillis" , t ); - return b.obj(); +int TimerStats::record(const Timer& timer) { + int millis = timer.millis(); + recordMillis(millis); + return millis; +} +BSONObj TimerStats::getReport() const { + long long n, t; + { + scoped_spinlock lk(_lock); + n = _num; + t = _totalMillis; } + BSONObjBuilder b(64); + b.appendNumber("num", n); + b.appendNumber("totalMillis", t); + return b.obj(); +} } diff --git a/src/mongo/db/stats/timer_stats.h b/src/mongo/db/stats/timer_stats.h index 9e3c4db5e5a..a1b3ef69dfd 100644 --- a/src/mongo/db/stats/timer_stats.h +++ b/src/mongo/db/stats/timer_stats.h @@ -36,54 +36,58 @@ namespace mongo { +/** + * Holds timing information in milliseconds + * keeps track of number of times and total milliseconds + * so a diff can be computed + */ +class TimerStats { +public: + void recordMillis(int millis); + /** - * Holds timing information in milliseconds - * keeps track of number of times and total milliseconds - * so a diff can be computed + * @return number of millis */ - class TimerStats { - public: - void recordMillis( int millis ); + int record(const Timer& timer); - /** - * @return number of millis - */ - int record( const Timer& timer ); + BSONObj getReport() const; + operator BSONObj() const { + return getReport(); + } - BSONObj getReport() const; - operator BSONObj() const { return getReport(); } +private: + mutable SpinLock _lock; + long long _num; + long long _totalMillis; +}; - private: - mutable SpinLock _lock; - long long _num; - long long _totalMillis; - }; +/** + * Holds an instance of a Timer such that we the time is recorded + * when the TimerHolder goes out of scope + */ +class TimerHolder { +public: + /** Destructor will record to TimerStats */ + TimerHolder(TimerStats* stats); + /** Will record stats if recordMillis hasn't (based on _recorded) */ + ~TimerHolder(); /** - * Holds an instance of a Timer such that we the time is recorded - * when the TimerHolder goes out of scope + * returns elapsed millis from internal timer */ - class TimerHolder { - public: - /** Destructor will record to TimerStats */ - TimerHolder( TimerStats* stats ); - /** Will record stats if recordMillis hasn't (based on _recorded) */ - ~TimerHolder(); + int millis() const { + return _t.millis(); + } - /** - * returns elapsed millis from internal timer - */ - int millis() const { return _t.millis(); } - - /** - * records the time in the TimerStats and marks that we've - * already recorded so the destructor doesn't - */ - int recordMillis(); + /** + * records the time in the TimerStats and marks that we've + * already recorded so the destructor doesn't + */ + int recordMillis(); - private: - TimerStats* _stats; - bool _recorded; - Timer _t; - }; +private: + TimerStats* _stats; + bool _recorded; + Timer _t; +}; } diff --git a/src/mongo/db/stats/top.cpp b/src/mongo/db/stats/top.cpp index 903378e1834..f4f66d42a05 100644 --- a/src/mongo/db/stats/top.cpp +++ b/src/mongo/db/stats/top.cpp @@ -40,86 +40,84 @@ namespace mongo { - using std::endl; - using std::string; - using std::stringstream; - using std::vector; +using std::endl; +using std::string; +using std::stringstream; +using std::vector; namespace { - const auto getTop = ServiceContext::declareDecoration<Top>(); +const auto getTop = ServiceContext::declareDecoration<Top>(); -} // namespace +} // namespace - Top::UsageData::UsageData( const UsageData& older, const UsageData& newer ) { - // this won't be 100% accurate on rollovers and drop(), but at least it won't be negative - time = (newer.time >= older.time) ? (newer.time - older.time) : newer.time; - count = (newer.count >= older.count) ? (newer.count - older.count) : newer.count; - } - - Top::CollectionData::CollectionData( const CollectionData& older, const CollectionData& newer ) - : total( older.total, newer.total ), - readLock( older.readLock, newer.readLock ), - writeLock( older.writeLock, newer.writeLock ), - queries( older.queries, newer.queries ), - getmore( older.getmore, newer.getmore ), - insert( older.insert, newer.insert ), - update( older.update, newer.update ), - remove( older.remove, newer.remove ), - commands( older.commands, newer.commands ) { - - } - - // static - Top& Top::get(ServiceContext* service) { - return getTop(service); - } +Top::UsageData::UsageData(const UsageData& older, const UsageData& newer) { + // this won't be 100% accurate on rollovers and drop(), but at least it won't be negative + time = (newer.time >= older.time) ? (newer.time - older.time) : newer.time; + count = (newer.count >= older.count) ? (newer.count - older.count) : newer.count; +} - void Top::record( StringData ns, int op, int lockType, long long micros, bool command ) { - if ( ns[0] == '?' ) - return; +Top::CollectionData::CollectionData(const CollectionData& older, const CollectionData& newer) + : total(older.total, newer.total), + readLock(older.readLock, newer.readLock), + writeLock(older.writeLock, newer.writeLock), + queries(older.queries, newer.queries), + getmore(older.getmore, newer.getmore), + insert(older.insert, newer.insert), + update(older.update, newer.update), + remove(older.remove, newer.remove), + commands(older.commands, newer.commands) {} + +// static +Top& Top::get(ServiceContext* service) { + return getTop(service); +} - //cout << "record: " << ns << "\t" << op << "\t" << command << endl; - stdx::lock_guard<SimpleMutex> lk(_lock); +void Top::record(StringData ns, int op, int lockType, long long micros, bool command) { + if (ns[0] == '?') + return; - if ( ( command || op == dbQuery ) && ns == _lastDropped ) { - _lastDropped = ""; - return; - } + // cout << "record: " << ns << "\t" << op << "\t" << command << endl; + stdx::lock_guard<SimpleMutex> lk(_lock); - CollectionData& coll = _usage[ns]; - _record( coll, op, lockType, micros, command ); + if ((command || op == dbQuery) && ns == _lastDropped) { + _lastDropped = ""; + return; } - void Top::_record( CollectionData& c, int op, int lockType, long long micros, bool command ) { - c.total.inc( micros ); + CollectionData& coll = _usage[ns]; + _record(coll, op, lockType, micros, command); +} + +void Top::_record(CollectionData& c, int op, int lockType, long long micros, bool command) { + c.total.inc(micros); - if ( lockType > 0 ) - c.writeLock.inc( micros ); - else if ( lockType < 0 ) - c.readLock.inc( micros ); + if (lockType > 0) + c.writeLock.inc(micros); + else if (lockType < 0) + c.readLock.inc(micros); - switch ( op ) { + switch (op) { case 0: // use 0 for unknown, non-specific break; case dbUpdate: - c.update.inc( micros ); + c.update.inc(micros); break; case dbInsert: - c.insert.inc( micros ); + c.insert.inc(micros); break; case dbQuery: - if ( command ) - c.commands.inc( micros ); + if (command) + c.commands.inc(micros); else - c.queries.inc( micros ); + c.queries.inc(micros); break; case dbGetMore: - c.getmore.inc( micros ); + c.getmore.inc(micros); break; case dbDelete: - c.remove.inc( micros ); + c.remove.inc(micros); break; case dbKillCursors: break; @@ -133,62 +131,60 @@ namespace { break; default: log() << "unknown op in Top::record: " << op << endl; - } - - } - - void Top::collectionDropped( StringData ns ) { - stdx::lock_guard<SimpleMutex> lk(_lock); - _usage.erase(ns); - _lastDropped = ns.toString(); } +} - void Top::cloneMap(Top::UsageMap& out) const { - stdx::lock_guard<SimpleMutex> lk(_lock); - out = _usage; - } +void Top::collectionDropped(StringData ns) { + stdx::lock_guard<SimpleMutex> lk(_lock); + _usage.erase(ns); + _lastDropped = ns.toString(); +} - void Top::append( BSONObjBuilder& b ) { - stdx::lock_guard<SimpleMutex> lk( _lock ); - _appendToUsageMap( b, _usage ); - } +void Top::cloneMap(Top::UsageMap& out) const { + stdx::lock_guard<SimpleMutex> lk(_lock); + out = _usage; +} - void Top::_appendToUsageMap( BSONObjBuilder& b, const UsageMap& map ) const { - // pull all the names into a vector so we can sort them for the user +void Top::append(BSONObjBuilder& b) { + stdx::lock_guard<SimpleMutex> lk(_lock); + _appendToUsageMap(b, _usage); +} - vector<string> names; - for ( UsageMap::const_iterator i = map.begin(); i != map.end(); ++i ) { - names.push_back( i->first ); - } +void Top::_appendToUsageMap(BSONObjBuilder& b, const UsageMap& map) const { + // pull all the names into a vector so we can sort them for the user - std::sort( names.begin(), names.end() ); + vector<string> names; + for (UsageMap::const_iterator i = map.begin(); i != map.end(); ++i) { + names.push_back(i->first); + } - for ( size_t i=0; i<names.size(); i++ ) { - BSONObjBuilder bb( b.subobjStart( names[i] ) ); + std::sort(names.begin(), names.end()); - const CollectionData& coll = map.find(names[i])->second; + for (size_t i = 0; i < names.size(); i++) { + BSONObjBuilder bb(b.subobjStart(names[i])); - _appendStatsEntry( b, "total", coll.total ); + const CollectionData& coll = map.find(names[i])->second; - _appendStatsEntry( b, "readLock", coll.readLock ); - _appendStatsEntry( b, "writeLock", coll.writeLock ); + _appendStatsEntry(b, "total", coll.total); - _appendStatsEntry( b, "queries", coll.queries ); - _appendStatsEntry( b, "getmore", coll.getmore ); - _appendStatsEntry( b, "insert", coll.insert ); - _appendStatsEntry( b, "update", coll.update ); - _appendStatsEntry( b, "remove", coll.remove ); - _appendStatsEntry( b, "commands", coll.commands ); + _appendStatsEntry(b, "readLock", coll.readLock); + _appendStatsEntry(b, "writeLock", coll.writeLock); - bb.done(); - } - } + _appendStatsEntry(b, "queries", coll.queries); + _appendStatsEntry(b, "getmore", coll.getmore); + _appendStatsEntry(b, "insert", coll.insert); + _appendStatsEntry(b, "update", coll.update); + _appendStatsEntry(b, "remove", coll.remove); + _appendStatsEntry(b, "commands", coll.commands); - void Top::_appendStatsEntry( BSONObjBuilder& b, const char * statsName, const UsageData& map ) const { - BSONObjBuilder bb( b.subobjStart( statsName ) ); - bb.appendNumber( "time", map.time ); - bb.appendNumber( "count", map.count ); bb.done(); } +} +void Top::_appendStatsEntry(BSONObjBuilder& b, const char* statsName, const UsageData& map) const { + BSONObjBuilder bb(b.subobjStart(statsName)); + bb.appendNumber("time", map.time); + bb.appendNumber("count", map.count); + bb.done(); +} } diff --git a/src/mongo/db/stats/top.h b/src/mongo/db/stats/top.h index d71605e8ef4..56090b5c408 100644 --- a/src/mongo/db/stats/top.h +++ b/src/mongo/db/stats/top.h @@ -36,66 +36,65 @@ namespace mongo { - class ServiceContext; - - /** - * tracks usage by collection - */ - class Top { - - public: - static Top& get(ServiceContext* service); - - Top() = default; - - struct UsageData { - UsageData() : time(0), count(0) {} - UsageData( const UsageData& older, const UsageData& newer ); - long long time; - long long count; - - void inc( long long micros ) { - count++; - time += micros; - } - }; - - struct CollectionData { - /** - * constructs a diff - */ - CollectionData() {} - CollectionData( const CollectionData& older, const CollectionData& newer ); - - UsageData total; - - UsageData readLock; - UsageData writeLock; - - UsageData queries; - UsageData getmore; - UsageData insert; - UsageData update; - UsageData remove; - UsageData commands; - }; - - typedef StringMap<CollectionData> UsageMap; - - public: - void record( StringData ns, int op, int lockType, long long micros, bool command ); - void append( BSONObjBuilder& b ); - void cloneMap(UsageMap& out) const; - void collectionDropped( StringData ns ); - - private: - void _appendToUsageMap( BSONObjBuilder& b, const UsageMap& map ) const; - void _appendStatsEntry( BSONObjBuilder& b, const char * statsName, const UsageData& map ) const; - void _record( CollectionData& c, int op, int lockType, long long micros, bool command ); - - mutable SimpleMutex _lock; - UsageMap _usage; - std::string _lastDropped; +class ServiceContext; + +/** + * tracks usage by collection + */ +class Top { +public: + static Top& get(ServiceContext* service); + + Top() = default; + + struct UsageData { + UsageData() : time(0), count(0) {} + UsageData(const UsageData& older, const UsageData& newer); + long long time; + long long count; + + void inc(long long micros) { + count++; + time += micros; + } }; -} // namespace mongo + struct CollectionData { + /** + * constructs a diff + */ + CollectionData() {} + CollectionData(const CollectionData& older, const CollectionData& newer); + + UsageData total; + + UsageData readLock; + UsageData writeLock; + + UsageData queries; + UsageData getmore; + UsageData insert; + UsageData update; + UsageData remove; + UsageData commands; + }; + + typedef StringMap<CollectionData> UsageMap; + +public: + void record(StringData ns, int op, int lockType, long long micros, bool command); + void append(BSONObjBuilder& b); + void cloneMap(UsageMap& out) const; + void collectionDropped(StringData ns); + +private: + void _appendToUsageMap(BSONObjBuilder& b, const UsageMap& map) const; + void _appendStatsEntry(BSONObjBuilder& b, const char* statsName, const UsageData& map) const; + void _record(CollectionData& c, int op, int lockType, long long micros, bool command); + + mutable SimpleMutex _lock; + UsageMap _usage; + std::string _lastDropped; +}; + +} // namespace mongo diff --git a/src/mongo/db/stats/top_test.cpp b/src/mongo/db/stats/top_test.cpp index 8aa5bc6363d..27ed6397ed6 100644 --- a/src/mongo/db/stats/top_test.cpp +++ b/src/mongo/db/stats/top_test.cpp @@ -33,10 +33,10 @@ namespace { - using namespace mongo; +using namespace mongo; - TEST(TopTest, CollectionDropped) { - Top().collectionDropped("coll"); - } +TEST(TopTest, CollectionDropped) { + Top().collectionDropped("coll"); +} -} // namespace +} // namespace |