// 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 . */ #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::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; }