17#include <boost/utility/string_view_fwd.hpp>
20#include <boost/algorithm/string/replace.hpp>
21#include <boost/utility/string_view.hpp>
24#include "hazelcast/client/client_config.h"
25#include "hazelcast/client/client_properties.h"
26#include "hazelcast/client/connection/ClientConnectionManagerImpl.h"
27#include "hazelcast/client/connection/Connection.h"
28#include "hazelcast/client/impl/metrics/metrics_compressor.h"
29#include "hazelcast/client/impl/metrics/metric_descriptor.h"
30#include "hazelcast/client/impl/statistics/Statistics.h"
31#include "hazelcast/client/internal/nearcache/NearCache.h"
32#include "hazelcast/client/internal/nearcache/NearCacheManager.h"
33#include "hazelcast/client/monitor/impl/LocalMapStatsImpl.h"
34#include "hazelcast/client/monitor/impl/NearCacheStatsImpl.h"
35#include "hazelcast/client/protocol/codec/codecs.h"
36#include "hazelcast/client/protocol/codec/codecs.h"
37#include "hazelcast/client/spi/ClientContext.h"
38#include "hazelcast/client/spi/impl/ClientExecutionServiceImpl.h"
39#include "hazelcast/client/spi/impl/ClientInvocation.h"
40#include "hazelcast/client/spi/lifecycle_service.h"
46const std::string Statistics::NEAR_CACHE_CATEGORY_PREFIX(
"nc.");
48Statistics::Statistics(spi::ClientContext& client_context)
49 : client_context_(client_context)
50 , client_properties_(client_context.get_client_properties())
51 , logger_(client_context.get_logger())
52 , periodic_stats_(*this)
54 this->enabled_ = client_properties_.get_boolean(
55 client_properties_.get_statistics_enabled());
65 int64_t periodSeconds = client_properties_.get_long(
66 client_properties_.get_statistics_period_seconds());
67 if (periodSeconds <= 0) {
69 int64_t defaultValue = util::IOUtil::to_value<int64_t>(
70 client_properties_.get_statistics_period_seconds()
71 .get_default_value());
76 boost::format(
"Provided client statistics %1% cannot be less than "
78 "You provided %2% seconds as the configuration. "
79 "Client will use the default value of %3% instead.") %
80 client_properties_.get_statistics_period_seconds().get_name() %
81 periodSeconds % defaultValue));
82 periodSeconds = defaultValue;
85 schedule_periodic_statistics_send_task(periodSeconds);
91 boost::format(
"Client statistics is enabled with period %1% seconds.") %
98 if (send_task_timer_) {
99 send_task_timer_->cancel();
104Statistics::schedule_periodic_statistics_send_task(int64_t period_seconds)
107 client_context_.get_client_execution_service().schedule_with_repetition(
109 if (!client_context_.get_lifecycle_service().is_running()) {
113 auto collection_timestamp =
114 std::chrono::duration_cast<std::chrono::milliseconds>(
115 std::chrono::system_clock::now().time_since_epoch())
117 std::shared_ptr<connection::Connection> connection =
122 "Cannot send client statistics to the server. No "
123 "connection found.");
127 std::ostringstream stats;
128 metrics::metrics_compressor metrics_comp;
130 periodic_stats_.fill_metrics(stats, metrics_comp, connection);
132 periodic_stats_.add_near_cache_stats(stats, metrics_comp);
134 send_stats(collection_timestamp,
136 metrics_comp.get_blob(),
139 std::chrono::seconds(0),
140 std::chrono::seconds(period_seconds));
143std::shared_ptr<connection::Connection>
144Statistics::get_connection()
146 return client_context_.get_connection_manager().get_random_connection();
150Statistics::send_stats(
152 const std::string& new_stats,
153 const std::vector<byte> metrics_blob,
154 const std::shared_ptr<connection::Connection>& connection)
156 auto request = protocol::codec::client_statistics_encode(
157 timestamp, new_stats, metrics_blob);
159 spi::impl::ClientInvocation::create(
160 client_context_, request,
"", connection)
163 }
catch (exception::iexception& e) {
167 boost::str(boost::format(
"Could not send stats %1%") % e));
172Statistics::PeriodicStatistics::fill_metrics(
173 std::ostringstream& stats,
174 metrics::metrics_compressor& compressor,
175 const std::shared_ptr<connection::Connection>& connection)
177 stats <<
"lastStatisticsCollectionTime" << KEY_VALUE_SEPARATOR
178 << util::current_time_millis();
179 add_stat(stats,
"enterprise",
false);
180 add_stat(stats,
"clientType", protocol::ClientTypes::CPP);
181 add_stat(stats,
"clientVersion", HAZELCAST_VERSION);
183 "clusterConnectionTimestamp",
184 std::chrono::duration_cast<std::chrono::milliseconds>(
185 connection->get_start_time().time_since_epoch())
188 auto localSocketAddress = connection->get_local_socket_address();
189 stats << STAT_SEPARATOR <<
"clientAddress" << KEY_VALUE_SEPARATOR;
190 if (localSocketAddress) {
191 stats << localSocketAddress->get_host() <<
":"
192 << localSocketAddress->get_port();
195 add_stat(stats,
"clientName", statistics_.client_context_.get_name());
198 statistics_.client_context_.get_client_config().get_credentials();
200 add_stat(stats,
"credentials.principal", credential->name());
203 auto hw_concurrency = std::thread::hardware_concurrency();
205 add_stat(stats,
"runtime.availableProcessors", hw_concurrency);
207 {
"runtime",
"availableProcessors", metrics::probe_unit::COUNT },
214Statistics::PeriodicStatistics::add_near_cache_stats(
215 std::ostringstream& stats,
216 metrics::metrics_compressor& compressor)
218 for (
auto near_cache : statistics_.client_context_.get_near_cache_manager()
219 .list_all_near_caches()) {
220 std::string nc_name = near_cache->get_name();
222 std::ostringstream nc_name_with_prefix_strm;
223 get_name_with_prefix(nc_name, nc_name_with_prefix_strm);
224 nc_name_with_prefix_strm <<
'.';
225 std::string nc_name_with_prefix = nc_name_with_prefix_strm.str();
228 std::static_pointer_cast<monitor::impl::NearCacheStatsImpl>(
229 near_cache->get_near_cache_stats());
231 add_near_cache_metric(stats,
236 nc_stats->get_creation_time(),
237 metrics::probe_unit::MS);
239 add_near_cache_metric(stats,
244 nc_stats->get_evictions(),
245 metrics::probe_unit::COUNT);
247 add_near_cache_metric(stats,
252 nc_stats->get_hits(),
253 metrics::probe_unit::COUNT);
255 add_near_cache_metric(stats,
257 "lastPersistenceDuration",
260 nc_stats->get_last_persistence_duration(),
261 metrics::probe_unit::MS);
263 add_near_cache_metric(stats,
265 "lastPersistenceKeyCount",
268 nc_stats->get_last_persistence_key_count(),
269 metrics::probe_unit::COUNT);
271 add_near_cache_metric(stats,
273 "lastPersistenceTime",
276 nc_stats->get_last_persistence_time(),
277 metrics::probe_unit::MS);
279 add_near_cache_metric(stats,
281 "lastPersistenceWrittenBytes",
284 nc_stats->get_last_persistence_written_bytes(),
285 metrics::probe_unit::BYTES);
287 add_near_cache_metric(stats,
292 nc_stats->get_misses(),
293 metrics::probe_unit::COUNT);
295 add_near_cache_metric(stats,
300 nc_stats->get_owned_entry_count(),
301 metrics::probe_unit::COUNT);
303 add_near_cache_metric(stats,
308 nc_stats->get_expirations(),
309 metrics::probe_unit::COUNT);
311 add_near_cache_metric(stats,
316 nc_stats->get_invalidations(),
317 metrics::probe_unit::COUNT);
319 add_near_cache_metric(stats,
321 "invalidationRequests",
324 nc_stats->get_invalidation_requests(),
325 metrics::probe_unit::COUNT);
327 add_near_cache_metric(stats,
329 "ownedEntryMemoryCost",
332 nc_stats->get_owned_entry_memory_cost(),
333 metrics::probe_unit::BYTES);
338Statistics::PeriodicStatistics::add_near_cache_metric(
339 std::ostringstream& stats,
340 metrics::metrics_compressor& compressor,
341 const std::string& metric,
342 const std::string& near_cache_name,
343 const std::string& near_cache_name_with_prefix,
345 metrics::probe_unit unit)
348 metrics::metric_descriptor desc{
349 "nearcache", metric,
"name", near_cache_name, unit
351 compressor.add_long(desc, value);
354 add_stat(stats, near_cache_name_with_prefix, metric, value);
357Statistics::PeriodicStatistics::PeriodicStatistics(Statistics& statistics)
358 : statistics_(statistics)
362Statistics::escape_special_characters(std::string& name)
364 boost::replace_all(name,
",",
"\\,");
365 boost::replace_all(name,
"=",
"\\=");
366 boost::replace_all(name,
"\\",
"\\\\");
368 return name[0] ==
'/' ? name.substr(1) : name;
372Statistics::PeriodicStatistics::get_name_with_prefix(std::string& name,
373 std::ostringstream& out)
375 out << NEAR_CACHE_CATEGORY_PREFIX
376 << Statistics::escape_special_characters(name);
381Statistics::PeriodicStatistics::add_stat(std::ostringstream& stats,
382 const std::string& name,
385 stats << STAT_SEPARATOR << name << KEY_VALUE_SEPARATOR
386 << (value ?
"true" :
"false");
393const int64_t local_instance_stats::STAT_NOT_AVAILABLE = -99L;
396LocalMapStatsImpl::LocalMapStatsImpl() =
default;
398LocalMapStatsImpl::LocalMapStatsImpl(
399 const std::shared_ptr<monitor::near_cache_stats>& s)
400 : near_cache_stats_(s)
403std::shared_ptr<monitor::near_cache_stats>
404LocalMapStatsImpl::get_near_cache_stats()
const
406 return near_cache_stats_;
409NearCacheStatsImpl::NearCacheStatsImpl()
410 : creation_time_(util::current_time_millis())
411 , owned_entry_count_(0)
412 , owned_entry_memory_cost_(0)
418 , invalidation_requests_(0)
419 , persistence_count_(0)
420 , last_persistence_time_(0)
421 , last_persistence_duration_(0)
422 , last_persistence_written_bytes_(0)
423 , last_persistence_key_count_(0)
424 , last_persistence_failure_(
"")
428NearCacheStatsImpl::get_creation_time()
430 return creation_time_;
434NearCacheStatsImpl::get_owned_entry_count()
436 return owned_entry_count_;
440NearCacheStatsImpl::set_owned_entry_count(int64_t owned_entry_count)
442 this->owned_entry_count_ = owned_entry_count;
446NearCacheStatsImpl::increment_owned_entry_count()
448 ++owned_entry_count_;
452NearCacheStatsImpl::decrement_owned_entry_count()
454 --owned_entry_count_;
458NearCacheStatsImpl::get_owned_entry_memory_cost()
460 return owned_entry_memory_cost_;
464NearCacheStatsImpl::set_owned_entry_memory_cost(int64_t owned_entry_memory_cost)
466 this->owned_entry_memory_cost_ = owned_entry_memory_cost;
470NearCacheStatsImpl::increment_owned_entry_memory_cost(
471 int64_t owned_entry_memory_cost)
473 this->owned_entry_memory_cost_ += owned_entry_memory_cost;
477NearCacheStatsImpl::decrement_owned_entry_memory_cost(
478 int64_t owned_entry_memory_cost)
480 this->owned_entry_memory_cost_ -= owned_entry_memory_cost;
484NearCacheStatsImpl::get_hits()
491NearCacheStatsImpl::set_hits(int64_t hits)
497NearCacheStatsImpl::increment_hits()
503NearCacheStatsImpl::get_misses()
510NearCacheStatsImpl::set_misses(int64_t misses)
512 this->misses_ = misses;
516NearCacheStatsImpl::increment_misses()
522NearCacheStatsImpl::get_ratio()
524 if (misses_ == (int64_t)0) {
525 if (hits_ == (int64_t)0) {
526 return std::numeric_limits<double>::signaling_NaN();
528 return std::numeric_limits<double>::infinity();
531 return ((
double)hits_ / misses_) * PERCENTAGE;
536NearCacheStatsImpl::get_evictions()
542NearCacheStatsImpl::increment_evictions()
548NearCacheStatsImpl::get_expirations()
554NearCacheStatsImpl::increment_expirations()
560NearCacheStatsImpl::get_invalidations()
562 return invalidations_.load();
566NearCacheStatsImpl::increment_invalidations()
572NearCacheStatsImpl::get_invalidation_requests()
574 return invalidation_requests_.load();
578NearCacheStatsImpl::increment_invalidation_requests()
580 ++invalidation_requests_;
584NearCacheStatsImpl::reset_invalidation_events()
586 invalidation_requests_ = 0;
590NearCacheStatsImpl::get_persistence_count()
592 return persistence_count_;
596NearCacheStatsImpl::add_persistence(int64_t duration,
597 int32_t written_bytes,
600 ++persistence_count_;
601 last_persistence_time_ = util::current_time_millis();
602 last_persistence_duration_ = duration;
603 last_persistence_written_bytes_ = written_bytes;
604 last_persistence_key_count_ = key_count;
605 last_persistence_failure_ =
"";
609NearCacheStatsImpl::get_last_persistence_time()
611 return last_persistence_time_;
615NearCacheStatsImpl::get_last_persistence_duration()
617 return last_persistence_duration_;
621NearCacheStatsImpl::get_last_persistence_written_bytes()
623 return last_persistence_written_bytes_;
627NearCacheStatsImpl::get_last_persistence_key_count()
629 return last_persistence_key_count_;
633NearCacheStatsImpl::get_last_persistence_failure()
635 return last_persistence_failure_;
639NearCacheStatsImpl::to_string()
641 std::ostringstream out;
642 std::string failureString = last_persistence_failure_;
643 out <<
"NearCacheStatsImpl{"
644 <<
"ownedEntryCount=" << owned_entry_count_
645 <<
", ownedEntryMemoryCost=" << owned_entry_memory_cost_
646 <<
", creationTime=" << creation_time_ <<
", hits=" << hits_
647 <<
", misses=" << misses_ <<
", ratio=" << std::setprecision(1)
648 << get_ratio() <<
", evictions=" << evictions_
649 <<
", expirations=" << expirations_
650 <<
", invalidations=" << invalidations_.load()
651 <<
", invalidationRequests=" << invalidation_requests_.load()
652 <<
", lastPersistenceTime=" << last_persistence_time_
653 <<
", persistenceCount=" << persistence_count_
654 <<
", lastPersistenceDuration=" << last_persistence_duration_
655 <<
", lastPersistenceWrittenBytes=" << last_persistence_written_bytes_
656 <<
", lastPersistenceKeyCount=" << last_persistence_key_count_
657 <<
", lastPersistenceFailure='" << failureString <<
"'" <<
'}';
662const double NearCacheStatsImpl::PERCENTAGE = 100.0;