diff --git a/Builds/VisualStudio2012/RippleD.vcxproj b/Builds/VisualStudio2012/RippleD.vcxproj index 07685c299c..92e3af490e 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj +++ b/Builds/VisualStudio2012/RippleD.vcxproj @@ -597,6 +597,12 @@ true true + + true + true + true + true + true true @@ -903,6 +909,12 @@ true true + + true + true + true + true + true true @@ -2250,6 +2262,7 @@ + @@ -2343,6 +2356,7 @@ + diff --git a/Builds/VisualStudio2012/RippleD.vcxproj.filters b/Builds/VisualStudio2012/RippleD.vcxproj.filters index 787623a4ae..e1aa4c36a9 100644 --- a/Builds/VisualStudio2012/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2012/RippleD.vcxproj.filters @@ -1386,6 +1386,12 @@ [2] Old Ripple\ripple_app\ledger + + [1] Ripple\rpc\impl + + + [2] Old Ripple\ripple_app\main + @@ -2850,6 +2856,12 @@ [1] Ripple\algorithm\api + + [1] Ripple\rpc\api + + + [2] Old Ripple\ripple_app\main + diff --git a/doc/rippled-example.cfg b/doc/rippled-example.cfg index ec028d64ba..c3678a9fcb 100644 --- a/doc/rippled-example.cfg +++ b/doc/rippled-example.cfg @@ -707,6 +707,41 @@ # # # +# [insight] +# +# Configuration parameters for the Beast.Insight stats collection module. +# +# Insight is a module that collects information from the areas of rippled +# that have instrumentation. The configuration paramters control where the +# collection metrics are sent. The parameters are expressed as key = value +# pairs with no white space. The main parameter is the choice of server: +# +# "server" +# +# Choice of server to send metrics to. Currently the only choice is +# "statsd" which sends UDP packets to a StatsD daemon, which must be +# running while rippled is running. More information on StatsD is +# available here: +# https://github.com/b/statsd_spec +# +# When server=statsd, these additional keys are used: +# +# "address" The UDP address and port of the listening StatsD server, +# in the format, n.n.n.n:port. +# +# "prefix" A string prepended to each collected metric. This is used +# to distinguish between different running instances of rippled. +# +# If this section is missing, or the server type is unspecified or unknown, +# statistics are not collected or reported. +# +# Example: +# +# [insight] +# server=statsd +# address=192.168.0.95:4201 +# prefix=my_validator +# #------------------------------------------------------------------------------- # Allow other peers to connect to this server. diff --git a/src/ripple/beast/ripple_beast.cpp b/src/ripple/beast/ripple_beast.cpp index b4a691264f..f12de1462b 100644 --- a/src/ripple/beast/ripple_beast.cpp +++ b/src/ripple/beast/ripple_beast.cpp @@ -43,6 +43,7 @@ #include "../beast/beast/chrono/Chrono.cpp" #include "../beast/beast/crypto/Crypto.cpp" #include "../beast/beast/http/HTTP.cpp" +#include "../beast/beast/insight/Insight.cpp" #include "../beast/beast/net/Net.cpp" #include "../beast/beast/smart_ptr/SmartPtr.cpp" #include "../beast/beast/strings/Strings.cpp" diff --git a/src/ripple_app/main/Application.cpp b/src/ripple_app/main/Application.cpp index 6a680ec8ac..135613df79 100644 --- a/src/ripple_app/main/Application.cpp +++ b/src/ripple_app/main/Application.cpp @@ -46,6 +46,8 @@ template <> char const* LogPartition::getPartitionName () { ret class ResourceManagerLog; template <> char const* LogPartition::getPartitionName () { return "ResourceManager"; } +template <> char const* LogPartition::getPartitionName () { return "Collector"; } + // //------------------------------------------------------------------------------ @@ -74,6 +76,10 @@ public: , m_tempNodeCache ("NodeCache", 16384, 90) , m_sleCache ("LedgerEntryCache", 4096, 120) + , m_collectorManager (CollectorManager::New ( + getConfig().insightSettings, + LogPartition::getJournal ())) + , m_resourceManager (add (Resource::Manager::New ( LogPartition::getJournal ()))) @@ -83,7 +89,9 @@ public: // The JobQueue has to come pretty early since // almost everything is a Stoppable child of the JobQueue. // - , m_jobQueue (JobQueue::New (*this, LogPartition::getJournal ())) + , m_jobQueue (JobQueue::New ( + m_collectorManager->collector (), + *this, LogPartition::getJournal ())) // The io_service must be a child of the JobQueue since we call addJob // in response to newtwork data from peers and also client requests. @@ -165,6 +173,11 @@ public: //-------------------------------------------------------------------------- + CollectorManager& getCollectorManager () + { + return *m_collectorManager; + } + RPC::Manager& getRPCServiceManager() { return *m_rpcServiceManager; @@ -882,6 +895,7 @@ private: LocalCredentials m_localCredentials; TransactionMaster m_txMaster; + beast::unique_ptr m_collectorManager; ScopedPointer m_resourceManager; ScopedPointer m_rpcServiceManager; diff --git a/src/ripple_app/main/Application.h b/src/ripple_app/main/Application.h index 12e5e11618..31081d6a40 100644 --- a/src/ripple_app/main/Application.h +++ b/src/ripple_app/main/Application.h @@ -27,6 +27,7 @@ namespace NodeStore { class Database; } namespace RPC { class Manager; } // VFALCO TODO Fix forward declares required for header dependency loops +class CollectorManager; class IFeatures; class IFeeVote; class IHashRouter; @@ -77,9 +78,8 @@ public: virtual ~Application () { } virtual boost::asio::io_service& getIOService () = 0; - + virtual CollectorManager& getCollectorManager () = 0; virtual RPC::Manager& getRPCServiceManager() = 0; - virtual JobQueue& getJobQueue () = 0; virtual SiteFiles::Manager& getSiteFiles () = 0; virtual NodeCache& getTempNodeCache () = 0; diff --git a/src/ripple_app/main/CollectorManager.cpp b/src/ripple_app/main/CollectorManager.cpp new file mode 100644 index 0000000000..3115c8be7a --- /dev/null +++ b/src/ripple_app/main/CollectorManager.cpp @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +namespace ripple { + +class CollectorManagerImp + : public CollectorManager +{ +public: + Journal m_journal; + shared_ptr m_collector; + + CollectorManagerImp (StringPairArray const& params, + Journal journal) + : m_journal (journal) + { + std::string const& server (params ["server"].toStdString()); + + if (server == "statsd") + { + IPAddress const address (IPAddress::from_string ( + params ["address"].toStdString ())); + std::string const& prefix (params ["prefix"].toStdString ()); + + m_collector = insight::StatsDCollector::New (address, prefix, journal); + } + else + { + m_collector = insight::NullCollector::New (); + } + } + + ~CollectorManagerImp () + { + } + + shared_ptr const& collector () + { + return m_collector; + } +}; + +//------------------------------------------------------------------------------ + +CollectorManager::~CollectorManager () +{ +} + +CollectorManager* CollectorManager::New (StringPairArray const& params, + Journal journal) +{ + return new CollectorManagerImp (params, journal); +} + +} diff --git a/src/ripple_app/main/CollectorManager.h b/src/ripple_app/main/CollectorManager.h new file mode 100644 index 0000000000..82ce026c54 --- /dev/null +++ b/src/ripple_app/main/CollectorManager.h @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_RIPPLECOLLECTOR_H_INCLUDED +#define RIPPLE_RIPPLECOLLECTOR_H_INCLUDED + +#include "beast/beast/Insight.h" + +namespace ripple { + +/** Provides the beast::insight::Collector service. */ +class CollectorManager +{ +public: + static CollectorManager* New (StringPairArray const& params, + Journal journal); + virtual ~CollectorManager () = 0; + virtual shared_ptr const& collector () = 0; +}; + +} + +#endif diff --git a/src/ripple_app/ripple_app.cpp b/src/ripple_app/ripple_app.cpp index 189e8aa330..9fa3d7293f 100644 --- a/src/ripple_app/ripple_app.cpp +++ b/src/ripple_app/ripple_app.cpp @@ -42,6 +42,9 @@ #include "beast/beast/Asio.h" +# include "main/CollectorManager.h" +#include "main/CollectorManager.cpp" + namespace ripple { // diff --git a/src/ripple_core/functional/Config.cpp b/src/ripple_core/functional/Config.cpp index 10bf021e89..bb3e6cdfea 100644 --- a/src/ripple_core/functional/Config.cpp +++ b/src/ripple_core/functional/Config.cpp @@ -331,6 +331,8 @@ void Config::load () (void) SectionSingleB (secConfig, SECTION_RPC_PASSWORD, RPC_PASSWORD); (void) SectionSingleB (secConfig, SECTION_RPC_USER, RPC_USER); + insightSettings = parseKeyValueSection (secConfig, SECTION_INSIGHT); + //--------------------------------------- // // VFALCO BEGIN CLEAN diff --git a/src/ripple_core/functional/Config.h b/src/ripple_core/functional/Config.h index 80d7178e50..9f69204883 100644 --- a/src/ripple_core/functional/Config.h +++ b/src/ripple_core/functional/Config.h @@ -298,6 +298,9 @@ public: //-------------------------------------------------------------------------- + /** Parameters for the insight collection module */ + StringPairArray insightSettings; + /** Parameters for the main NodeStore database. This is 1 or more strings of the form = diff --git a/src/ripple_core/functional/ConfigSections.h b/src/ripple_core/functional/ConfigSections.h index a77c28bbb6..994615f80a 100644 --- a/src/ripple_core/functional/ConfigSections.h +++ b/src/ripple_core/functional/ConfigSections.h @@ -47,6 +47,7 @@ struct ConfigSection #define SECTION_FEE_ACCOUNT_RESERVE "fee_account_reserve" #define SECTION_FEE_OWNER_RESERVE "fee_owner_reserve" #define SECTION_LEDGER_HISTORY "ledger_history" +#define SECTION_INSIGHT "insight" #define SECTION_IPS "ips" #define SECTION_IPS_FIXED "ips_fixed" #define SECTION_NETWORK_QUORUM "network_quorum" diff --git a/src/ripple_core/functional/JobQueue.cpp b/src/ripple_core/functional/JobQueue.cpp index e9b00e4958..2bebdac72d 100644 --- a/src/ripple_core/functional/JobQueue.cpp +++ b/src/ripple_core/functional/JobQueue.cpp @@ -22,6 +22,12 @@ class JobQueueImp , private Workers::Callback { public: + struct Metrics + { + insight::Hook hook; + insight::Gauge job_count; + }; + // Statistics for each JobType // struct Count @@ -53,6 +59,7 @@ public: typedef CriticalSection::ScopedLockType ScopedLock; Journal m_journal; + Metrics m_metrics; CriticalSection m_mutex; uint64 m_lastJob; JobSet m_jobSet; @@ -67,7 +74,8 @@ public: //-------------------------------------------------------------------------- - JobQueueImp (Stoppable& parent, Journal journal) + JobQueueImp (shared_ptr const& collector, + Stoppable& parent, Journal journal) : JobQueue ("JobQueue", parent) , m_journal (journal) , m_lastJob (0) @@ -75,6 +83,10 @@ public: , m_workers (*this, "JobQueue", 0) , m_cancelCallback (boost::bind (&Stoppable::isStopping, this)) { + m_metrics.hook = collector->make_hook (beast::bind ( + &JobQueueImp::collect, this)); + m_metrics.job_count = collector->make_gauge ("job_count"); + { ScopedLock lock (m_mutex); @@ -112,6 +124,12 @@ public: { } + void collect () + { + ScopedLock lock (m_mutex); + m_metrics.job_count = m_jobSet.size (); + } + void addJob (JobType type, const std::string& name, const FUNCTION_TYPE& jobFunc) { bassert (type != jtINVALID); @@ -708,7 +726,8 @@ JobQueue::JobQueue (char const* name, Stoppable& parent) //------------------------------------------------------------------------------ -JobQueue* JobQueue::New (Stoppable& parent, Journal journal) +JobQueue* JobQueue::New (shared_ptr const& collector, + Stoppable& parent, Journal journal) { - return new JobQueueImp (parent, journal); + return new JobQueueImp (collector, parent, journal); } diff --git a/src/ripple_core/functional/JobQueue.h b/src/ripple_core/functional/JobQueue.h index b0624fca0f..fd22585d67 100644 --- a/src/ripple_core/functional/JobQueue.h +++ b/src/ripple_core/functional/JobQueue.h @@ -26,7 +26,8 @@ protected: JobQueue (char const* name, Stoppable& parent); public: - static JobQueue* New (Stoppable& parent, Journal journal); + static JobQueue* New (shared_ptr const& collector, + Stoppable& parent, Journal journal); virtual ~JobQueue () { } diff --git a/src/ripple_core/ripple_core.h b/src/ripple_core/ripple_core.h index c59246ed27..d6c8109d0c 100644 --- a/src/ripple_core/ripple_core.h +++ b/src/ripple_core/ripple_core.h @@ -24,6 +24,7 @@ #include "../ripple_data/ripple_data.h" #include "beast/beast/http/URL.h" // for Config +#include "beast/beast/Insight.h" #include "../ripple/resource/api/LegacyFees.h"