diff options
Diffstat (limited to 'src/mongo/db/stats/counters.cpp')
-rw-r--r-- | src/mongo/db/stats/counters.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/mongo/db/stats/counters.cpp b/src/mongo/db/stats/counters.cpp new file mode 100644 index 00000000000..889e8a86c4c --- /dev/null +++ b/src/mongo/db/stats/counters.cpp @@ -0,0 +1,207 @@ +// counters.cpp +/* + * Copyright (C) 2010 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/>. + */ + + +#include "pch.h" +#include "../jsobj.h" +#include "counters.h" + +namespace mongo { + + OpCounters::OpCounters() { + int zero = 0; + + BSONObjBuilder b; + b.append( "insert" , zero ); + b.append( "query" , zero ); + b.append( "update" , zero ); + b.append( "delete" , zero ); + b.append( "getmore" , zero ); + b.append( "command" , zero ); + _obj = b.obj(); + + _insert = (AtomicUInt*)_obj["insert"].value(); + _query = (AtomicUInt*)_obj["query"].value(); + _update = (AtomicUInt*)_obj["update"].value(); + _delete = (AtomicUInt*)_obj["delete"].value(); + _getmore = (AtomicUInt*)_obj["getmore"].value(); + _command = (AtomicUInt*)_obj["command"].value(); + } + + void OpCounters::gotOp( int op , bool isCommand ) { + switch ( op ) { + case dbInsert: /*gotInsert();*/ break; // need to handle multi-insert + case dbQuery: + if ( isCommand ) + gotCommand(); + else + gotQuery(); + 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; + } + } + + BSONObj& OpCounters::getObj() { + const unsigned MAX = 1 << 30; + RARELY { + bool wrap = + _insert->get() > MAX || + _query->get() > MAX || + _update->get() > MAX || + _delete->get() > MAX || + _getmore->get() > MAX || + _command->get() > MAX; + + if ( wrap ) { + _insert->zero(); + _query->zero(); + _update->zero(); + _delete->zero(); + _getmore->zero(); + _command->zero(); + } + + } + return _obj; + } + + IndexCounters::IndexCounters() { + _memSupported = _pi.blockCheckSupported(); + + _btreeMemHits = 0; + _btreeMemMisses = 0; + _btreeAccesses = 0; + + + _maxAllowed = ( numeric_limits< long long >::max() ) / 2; + _resets = 0; + + _sampling = 0; + _samplingrate = 100; + } + + void IndexCounters::append( BSONObjBuilder& b ) { + if ( ! _memSupported ) { + b.append( "note" , "not supported on this platform" ); + return; + } + + BSONObjBuilder bb( b.subobjStart( "btree" ) ); + bb.appendNumber( "accesses" , _btreeAccesses ); + bb.appendNumber( "hits" , _btreeMemHits ); + bb.appendNumber( "misses" , _btreeMemMisses ); + + bb.append( "resets" , _resets ); + + bb.append( "missRatio" , (_btreeAccesses ? (_btreeMemMisses / (double)_btreeAccesses) : 0) ); + + bb.done(); + + if ( _btreeAccesses > _maxAllowed ) { + _btreeAccesses = 0; + _btreeMemMisses = 0; + _btreeMemHits = 0; + _resets++; + } + } + + FlushCounters::FlushCounters() + : _total_time(0) + , _flushes(0) + , _last() + {} + + void FlushCounters::flushed(int ms) { + _flushes++; + _total_time += ms; + _last_time = ms; + _last = jsTime(); + } + + void FlushCounters::append( BSONObjBuilder& b ) { + b.appendNumber( "flushes" , _flushes ); + b.appendNumber( "total_ms" , _total_time ); + b.appendNumber( "average_ms" , (_flushes ? (_total_time / double(_flushes)) : 0.0) ); + b.appendNumber( "last_ms" , _last_time ); + b.append("last_finished", _last); + } + + + void GenericCounter::hit( const string& name , int count ) { + scoped_lock lk( _mutex ); + _counts[name]++; + } + + BSONObj GenericCounter::getObj() { + BSONObjBuilder b(128); + { + mongo::mutex::scoped_lock lk( _mutex ); + for ( map<string,long long>::iterator i=_counts.begin(); i!=_counts.end(); i++ ) { + b.appendNumber( i->first , i->second ); + } + } + return b.obj(); + } + + + 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(); + } + } + + 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; + IndexCounters globalIndexCounters; + FlushCounters globalFlushCounters; + NetworkCounter networkCounter; + +} |