2013-02-28 05:45:47 -05:00
/******************************************************************************
* Icinga 2 *
2016-01-12 02:29:59 -05:00
* Copyright ( C ) 2012 - 2016 Icinga Development Team ( https : //www.icinga.org/) *
2013-02-28 05:45:47 -05:00
* *
* This program is free software ; you can redistribute it and / or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation ; either version 2 *
* of the License , or ( at your option ) any later version . *
* *
* 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 General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the Free Software Foundation *
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-05-25 10:23:35 -04:00
# include "perfdata/perfdatawriter.hpp"
2015-03-28 06:04:42 -04:00
# include "perfdata/perfdatawriter.tcpp"
2014-05-25 10:23:35 -04:00
# include "icinga/service.hpp"
# include "icinga/macroprocessor.hpp"
# include "icinga/icingaapplication.hpp"
2015-08-15 14:28:05 -04:00
# include "base/configtype.hpp"
2014-05-25 10:23:35 -04:00
# include "base/objectlock.hpp"
2014-10-19 08:21:12 -04:00
# include "base/logger.hpp"
2014-05-25 10:23:35 -04:00
# include "base/convert.hpp"
# include "base/utility.hpp"
# include "base/context.hpp"
2015-02-11 07:12:08 -05:00
# include "base/exception.hpp"
2014-05-25 10:23:35 -04:00
# include "base/application.hpp"
# include "base/statsfunction.hpp"
2013-02-28 05:45:47 -05:00
using namespace icinga ;
2013-03-01 06:07:52 -05:00
REGISTER_TYPE ( PerfdataWriter ) ;
2013-02-28 05:45:47 -05:00
2015-09-21 05:44:58 -04:00
REGISTER_STATSFUNCTION ( PerfdataWriter , & PerfdataWriter : : StatsFunc ) ;
2014-02-17 10:34:18 -05:00
2015-02-07 16:36:17 -05:00
void PerfdataWriter : : StatsFunc ( const Dictionary : : Ptr & status , const Array : : Ptr & )
2014-02-17 10:34:18 -05:00
{
2014-11-08 15:17:16 -05:00
Dictionary : : Ptr nodes = new Dictionary ( ) ;
2014-02-18 04:53:44 -05:00
2015-08-15 14:28:05 -04:00
BOOST_FOREACH ( const PerfdataWriter : : Ptr & perfdatawriter , ConfigType : : GetObjectsByType < PerfdataWriter > ( ) ) {
2014-02-18 04:53:44 -05:00
nodes - > Set ( perfdatawriter - > GetName ( ) , 1 ) ; //add more stats
}
status - > Set ( " perfdatawriter " , nodes ) ;
2014-02-17 10:34:18 -05:00
}
2015-08-20 11:18:48 -04:00
void PerfdataWriter : : Start ( bool runtimeCreated )
2013-02-28 05:45:47 -05:00
{
2015-08-20 11:18:48 -04:00
ObjectImpl < PerfdataWriter > : : Start ( runtimeCreated ) ;
2013-08-20 05:06:04 -04:00
2014-04-03 09:36:13 -04:00
Checkable : : OnNewCheckResult . connect ( boost : : bind ( & PerfdataWriter : : CheckResultHandler , this , _1 , _2 ) ) ;
2013-02-28 05:45:47 -05:00
2014-11-08 15:17:16 -05:00
m_RotationTimer = new Timer ( ) ;
2013-02-28 05:45:47 -05:00
m_RotationTimer - > OnTimerExpired . connect ( boost : : bind ( & PerfdataWriter : : RotationTimerHandler , this ) ) ;
m_RotationTimer - > SetInterval ( GetRotationInterval ( ) ) ;
m_RotationTimer - > Start ( ) ;
2014-04-01 14:30:44 -04:00
RotateFile ( m_ServiceOutputFile , GetServiceTempPath ( ) , GetServicePerfdataPath ( ) ) ;
RotateFile ( m_HostOutputFile , GetHostTempPath ( ) , GetHostPerfdataPath ( ) ) ;
2013-02-28 05:45:47 -05:00
}
2014-11-26 14:43:42 -05:00
Value PerfdataWriter : : EscapeMacroMetric ( const Value & value )
{
if ( value . IsObjectType < Array > ( ) )
return Utility : : Join ( value , ' ; ' ) ;
else
return value ;
}
2014-04-03 09:36:13 -04:00
void PerfdataWriter : : CheckResultHandler ( const Checkable : : Ptr & checkable , const CheckResult : : Ptr & cr )
2013-02-28 05:45:47 -05:00
{
2014-04-03 09:36:13 -04:00
CONTEXT ( " Writing performance data for object ' " + checkable - > GetName ( ) + " ' " ) ;
2013-12-02 07:34:23 -05:00
2014-04-03 09:36:13 -04:00
if ( ! IcingaApplication : : GetInstance ( ) - > GetEnablePerfdata ( ) | | ! checkable - > GetEnablePerfdata ( ) )
2013-10-08 05:57:35 -04:00
return ;
2014-04-03 09:36:13 -04:00
Service : : Ptr service = dynamic_pointer_cast < Service > ( checkable ) ;
Host : : Ptr host ;
if ( service )
host = service - > GetHost ( ) ;
else
host = static_pointer_cast < Host > ( checkable ) ;
2013-02-28 05:45:47 -05:00
2014-04-08 07:23:24 -04:00
MacroProcessor : : ResolverList resolvers ;
2014-04-03 09:36:13 -04:00
if ( service )
2014-04-08 07:23:24 -04:00
resolvers . push_back ( std : : make_pair ( " service " , service ) ) ;
resolvers . push_back ( std : : make_pair ( " host " , host ) ) ;
resolvers . push_back ( std : : make_pair ( " icinga " , IcingaApplication : : GetInstance ( ) ) ) ;
2013-03-22 09:40:55 -04:00
2014-04-03 09:36:13 -04:00
if ( service ) {
2014-11-26 14:43:42 -05:00
String line = MacroProcessor : : ResolveMacros ( GetServiceFormatTemplate ( ) , resolvers , cr , NULL , & PerfdataWriter : : EscapeMacroMetric ) ;
2014-04-01 14:30:44 -04:00
2014-04-03 09:36:13 -04:00
{
ObjectLock olock ( this ) ;
if ( ! m_ServiceOutputFile . good ( ) )
return ;
2013-02-28 05:45:47 -05:00
2014-04-03 09:36:13 -04:00
m_ServiceOutputFile < < line < < " \n " ;
}
} else {
2014-11-26 14:43:42 -05:00
String line = MacroProcessor : : ResolveMacros ( GetHostFormatTemplate ( ) , resolvers , cr , NULL , & PerfdataWriter : : EscapeMacroMetric ) ;
2014-04-01 14:30:44 -04:00
{
ObjectLock olock ( this ) ;
if ( ! m_HostOutputFile . good ( ) )
return ;
m_HostOutputFile < < line < < " \n " ;
}
}
2013-02-28 05:45:47 -05:00
}
2014-04-01 14:30:44 -04:00
void PerfdataWriter : : RotateFile ( std : : ofstream & output , const String & temp_path , const String & perfdata_path )
2013-02-28 05:45:47 -05:00
{
2013-03-02 03:07:47 -05:00
ObjectLock olock ( this ) ;
2014-04-01 14:30:44 -04:00
if ( output . good ( ) ) {
output . close ( ) ;
2013-02-28 05:45:47 -05:00
2014-04-01 14:30:44 -04:00
String finalFile = perfdata_path + " . " + Convert : : ToString ( ( long ) Utility : : GetTime ( ) ) ;
( void ) rename ( temp_path . CStr ( ) , finalFile . CStr ( ) ) ;
2013-02-28 05:45:47 -05:00
}
2014-04-01 14:30:44 -04:00
output . open ( temp_path . CStr ( ) ) ;
2013-02-28 05:45:47 -05:00
2014-04-01 14:30:44 -04:00
if ( ! output . good ( ) )
2014-10-19 11:52:17 -04:00
Log ( LogWarning , " PerfdataWriter " )
< < " Could not open perfdata file ' " < < temp_path < < " ' for writing. Perfdata will be lost. " ;
2013-02-28 05:45:47 -05:00
}
void PerfdataWriter : : RotationTimerHandler ( void )
{
2014-04-01 14:30:44 -04:00
RotateFile ( m_ServiceOutputFile , GetServiceTempPath ( ) , GetServicePerfdataPath ( ) ) ;
RotateFile ( m_HostOutputFile , GetHostTempPath ( ) , GetHostPerfdataPath ( ) ) ;
2013-02-28 05:45:47 -05:00
}
2013-08-20 05:06:04 -04:00
2014-11-30 17:32:13 -05:00
void PerfdataWriter : : ValidateHostFormatTemplate ( const String & value , const ValidationUtils & utils )
2015-02-11 07:12:08 -05:00
{
2014-11-30 17:32:13 -05:00
ObjectImpl < PerfdataWriter > : : ValidateHostFormatTemplate ( value , utils ) ;
2015-02-11 09:47:45 -05:00
2014-11-30 17:32:13 -05:00
if ( ! MacroProcessor : : ValidateMacroString ( value ) )
BOOST_THROW_EXCEPTION ( ValidationError ( this , boost : : assign : : list_of ( " host_format_template " ) , " Closing $ not found in macro format string ' " + value + " '. " ) ) ;
}
void PerfdataWriter : : ValidateServiceFormatTemplate ( const String & value , const ValidationUtils & utils )
{
ObjectImpl < PerfdataWriter > : : ValidateServiceFormatTemplate ( value , utils ) ;
if ( ! MacroProcessor : : ValidateMacroString ( value ) )
BOOST_THROW_EXCEPTION ( ValidationError ( this , boost : : assign : : list_of ( " service_format_template " ) , " Closing $ not found in macro format string ' " + value + " '. " ) ) ;
2015-02-11 09:47:45 -05:00
}