147 lines
4.4 KiB
C++
147 lines
4.4 KiB
C++
/**
|
|
* $LicenseInfo:firstyear=2013&license=fsviewerlgpl$
|
|
* Phoenix Firestorm Viewer Source Code
|
|
* Copyright (C) 2013, Nicky Dasmijn
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
|
* http://www.firestormviewer.org
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "ndlogthrottle.h"
|
|
#include <set>
|
|
|
|
#include "llpreprocessor.h"
|
|
#include "lltimer.h"
|
|
|
|
namespace nd
|
|
{
|
|
namespace logging
|
|
{
|
|
const U64 spamAvgInterval = 3 * 1000 * 1000; // 3 seconds
|
|
const U64 maxThrottle = 60 * 1000 * 1000; // 1 minute
|
|
const U64 minCallsBeforeThrottle = 250;
|
|
const U64 initialThrottle = 5*1000*1000; // 5 seconds
|
|
const U64 resetAfter = 30*1000*1000;
|
|
|
|
bool logThrottleEnabled = true;
|
|
|
|
struct CallSiteCall
|
|
{
|
|
char const *mFile;
|
|
int mLine;
|
|
mutable U64 mLastCall;
|
|
mutable U64 mAverage;
|
|
mutable U64 mCalls;
|
|
mutable U64 mThrottledCalls;
|
|
mutable U64 mLastUnthrottled;
|
|
mutable U32 mThrottle;
|
|
|
|
CallSiteCall( char const *aFile, int aLine )
|
|
: mFile( aFile )
|
|
, mLine( aLine )
|
|
, mLastCall( 0 )
|
|
, mAverage( 0 )
|
|
, mCalls( 0 )
|
|
, mThrottledCalls( 0 )
|
|
, mLastUnthrottled( 0 )
|
|
, mThrottle( initialThrottle )
|
|
{
|
|
}
|
|
|
|
bool operator< ( CallSiteCall const &aRHS ) const
|
|
{
|
|
if( mLine != aRHS.mLine )
|
|
return mLine < aRHS.mLine;
|
|
|
|
return mFile < aRHS.mFile;
|
|
}
|
|
};
|
|
|
|
bool throttle( char const *aFile, int aLine, std::ostream *aOut )
|
|
{
|
|
// Only called from Log::flush and protected by LogLock
|
|
|
|
if (!logThrottleEnabled)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static std::set< CallSiteCall > stCalls;
|
|
|
|
CallSiteCall oCall( aFile, aLine );
|
|
oCall.mLastCall = LLTimer::getTotalTime();
|
|
oCall.mLastUnthrottled = oCall.mLastCall;
|
|
|
|
std::set< CallSiteCall >::iterator itr = stCalls.find( oCall );
|
|
|
|
if( stCalls.end() == itr )
|
|
{
|
|
stCalls.insert( oCall );
|
|
return false;
|
|
}
|
|
|
|
U64 nDiffT = (oCall.mLastCall - itr->mLastCall);
|
|
U64 nDiffU = (oCall.mLastCall - itr->mLastUnthrottled);
|
|
|
|
if( nDiffT < resetAfter )
|
|
{
|
|
++itr->mCalls;
|
|
itr->mAverage = (itr->mAverage + nDiffT )/2;
|
|
itr->mLastCall = oCall.mLastCall;
|
|
}
|
|
else
|
|
{
|
|
itr->mCalls = 1;
|
|
itr->mAverage = 0;
|
|
itr->mLastCall = oCall.mLastCall;
|
|
itr->mLastUnthrottled = oCall.mLastCall;
|
|
itr->mThrottledCalls = 0;
|
|
itr->mThrottle = initialThrottle;
|
|
return false;
|
|
}
|
|
|
|
if( itr->mCalls > minCallsBeforeThrottle && itr->mAverage <= spamAvgInterval && nDiffU < itr->mThrottle )
|
|
{
|
|
++itr->mThrottledCalls;
|
|
return true;
|
|
}
|
|
|
|
itr->mLastUnthrottled = oCall.mLastCall;
|
|
|
|
if( itr->mThrottledCalls )
|
|
{
|
|
if( aOut )
|
|
*aOut << "( Supressed " << itr->mThrottledCalls << " calls, frequency " << itr->mAverage << " usec, throttle " << itr->mThrottle << " usec ) ";
|
|
|
|
if( itr->mThrottle < maxThrottle )
|
|
itr->mThrottle *= 2;
|
|
}
|
|
|
|
itr->mThrottledCalls = 0;
|
|
|
|
return false;
|
|
}
|
|
|
|
void setThrottleEnabled(bool enabled)
|
|
{
|
|
logThrottleEnabled = enabled;
|
|
}
|
|
}
|
|
}
|
|
|