Skip to content

Commit

Permalink
Review fixes
Browse files Browse the repository at this point in the history
Signed-off-by: Evgeny Malygin <[email protected]>
  • Loading branch information
678098 committed Jul 4, 2024
1 parent fbb70a8 commit 50b6ccf
Show file tree
Hide file tree
Showing 11 changed files with 355 additions and 288 deletions.
154 changes: 78 additions & 76 deletions src/groups/mqb/mqbstat/mqbstat_jsonprinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace {
// ---------------------

/// The implementation class for JsonPrinter, containing all the cached options
/// for printing statistics as json. This implementation exists and is hidden
/// for printing statistics as JSON. This implementation exists and is hidden
/// from the package include for the following reasons:
/// - Don't want to expose `bdljsn` names and symbols to the outer scope.
/// - Member fields and functions defined for this implementation are used only
Expand All @@ -52,20 +52,14 @@ class JsonPrinterImpl {

private:
// PRIVATE TYPES
typedef bsl::unordered_map<bsl::string, mwcst::StatContext*>
StatContextsMap;

typedef mqbstat::QueueStatsDomain::Stat Stat;
typedef JsonPrinter::StatContextsMap StatContextsMap;

private:
// DATA
/// Config to use
const mqbcfg::StatsConfig& d_config;

/// Options for printing a compact json
/// Options for printing a compact JSON
const bdljsn::WriteOptions d_opsCompact;

/// Options for printing a pretty json
/// Options for printing a pretty JSON
const bdljsn::WriteOptions d_opsPretty;

/// StatContext-s map
Expand All @@ -79,89 +73,98 @@ class JsonPrinterImpl {

// ACCESSORS

/// "domainQueues"
/// "domainQueues" stat context:
/// Populate the specified `bdljsn::JsonObject*` with the values
/// from the specified `ctx`.
void populateQueueValues(bdljsn::JsonObject* queueObject,
const mwcst::StatContext& ctx) const;
void populateQueueStats(bdljsn::JsonObject* domainObject,
const mwcst::StatContext& ctx) const;
void populateDomainQueueStats(bdljsn::JsonObject* parent,
const mwcst::StatContext& ctx) const;
static void populateAllDomainsStats(bdljsn::JsonObject* parent,
const mwcst::StatContext& ctx);
static void populateOneDomainStats(bdljsn::JsonObject* domainObject,
const mwcst::StatContext& ctx);
static void populateQueueStats(bdljsn::JsonObject* queueObject,
const mwcst::StatContext& ctx);
static void populateMetric(bdljsn::JsonObject* metricsObject,
const mwcst::StatContext& ctx,
mqbstat::QueueStatsDomain::Stat::Enum metric);

public:
// TRAITS
BSLMF_NESTED_TRAIT_DECLARATION(JsonPrinterImpl, bslma::UsesBslmaAllocator)

// CREATORS

/// Create a new `JsonPrinterImpl` object, using the specified `config`,
/// Create a new `JsonPrinterImpl` object, using the specified
/// `statContextsMap` and the specified `allocator`.
JsonPrinterImpl(const mqbcfg::StatsConfig& config,
const StatContextsMap& statContextsMap,
bslma::Allocator* allocator);
explicit JsonPrinterImpl(const StatContextsMap& statContextsMap,
bslma::Allocator* allocator);

// ACCESSORS

/// Print the json-encoded stats to the specified `out`.
/// If the specified `compact` flag is `true`, the json is printed in a
/// compact form, otherwise the json is printed in a pretty form.
/// Print the JSON-encoded stats to the specified `out`.
/// If the specified `compact` flag is `true`, the JSON is printed in a
/// compact form, otherwise the JSON is printed in a pretty form.
/// Return `0` on success, and non-zero return code on failure.
///
/// THREAD: This method is called in the *StatController scheduler* thread.
int printStats(bsl::string* out, bool compact) const;
};

inline JsonPrinterImpl::JsonPrinterImpl(const mqbcfg::StatsConfig& config,
const StatContextsMap& statContextsMap,
inline JsonPrinterImpl::JsonPrinterImpl(const StatContextsMap& statContextsMap,
bslma::Allocator* allocator)
: d_config(config)
, d_opsCompact(bdljsn::WriteOptions().setSpacesPerLevel(0).setStyle(
: d_opsCompact(bdljsn::WriteOptions().setSpacesPerLevel(0).setStyle(
bdljsn::WriteStyle::e_COMPACT))
, d_opsPretty(bdljsn::WriteOptions().setSpacesPerLevel(4).setStyle(
bdljsn::WriteStyle::e_PRETTY))
, d_contexts(statContextsMap, allocator)
{
// NOTHING
}

inline void
JsonPrinterImpl::populateQueueValues(bdljsn::JsonObject* queueObject,
const mwcst::StatContext& ctx) const
JsonPrinterImpl::populateMetric(bdljsn::JsonObject* metricsObject,
const mwcst::StatContext& ctx,
mqbstat::QueueStatsDomain::Stat::Enum metric)
{
// PRECONDITIONS
BSLS_ASSERT_SAFE(metricsObject);

const bsls::Types::Int64 value =
mqbstat::QueueStatsDomain::getValue(ctx, -1, metric);

(*metricsObject)[mqbstat::QueueStatsDomain::Stat::toString(metric)]
.makeNumber() = value;
}

inline void
JsonPrinterImpl::populateQueueStats(bdljsn::JsonObject* queueObject,
const mwcst::StatContext& ctx)
{
// PRECONDITIONS
BSLS_ASSERT_SAFE(queueObject);

static const bsl::vector<Stat::Enum> defs = {Stat::e_NB_PRODUCER,
Stat::e_NB_CONSUMER,
Stat::e_PUT_MESSAGES_DELTA,
Stat::e_PUT_BYTES_DELTA,
Stat::e_PUSH_MESSAGES_DELTA,
Stat::e_PUSH_BYTES_DELTA,
Stat::e_ACK_DELTA,
Stat::e_ACK_TIME_AVG,
Stat::e_ACK_TIME_MAX,
Stat::e_NACK_DELTA,
Stat::e_CONFIRM_DELTA,
Stat::e_CONFIRM_TIME_AVG,
Stat::e_CONFIRM_TIME_MAX};

if (ctx.numValues() > 0) {
bdljsn::JsonObject& values = (*queueObject)["values"].makeObject();

for (int i = 0; i < defs.size(); i++) {
Stat::Enum d = defs[i];

const bsls::Types::Int64 value =
mqbstat::QueueStatsDomain::getValue(ctx, -1, d);

values[Stat::toString(d)].makeNumber() = value;
}
if (ctx.numValues() == 0) {
// Prefer to omit an empty "values" object
return; // RETURN
}

bdljsn::JsonObject& values = (*queueObject)["values"].makeObject();

typedef mqbstat::QueueStatsDomain::Stat Stat;

populateMetric(&values, ctx, Stat::e_NB_PRODUCER);
populateMetric(&values, ctx, Stat::e_NB_CONSUMER);
populateMetric(&values, ctx, Stat::e_PUT_MESSAGES_DELTA);
populateMetric(&values, ctx, Stat::e_PUT_BYTES_DELTA);
populateMetric(&values, ctx, Stat::e_PUSH_MESSAGES_DELTA);
populateMetric(&values, ctx, Stat::e_PUSH_BYTES_DELTA);
populateMetric(&values, ctx, Stat::e_ACK_DELTA);
populateMetric(&values, ctx, Stat::e_ACK_TIME_AVG);
populateMetric(&values, ctx, Stat::e_ACK_TIME_MAX);
populateMetric(&values, ctx, Stat::e_NACK_DELTA);
populateMetric(&values, ctx, Stat::e_CONFIRM_DELTA);
populateMetric(&values, ctx, Stat::e_CONFIRM_TIME_AVG);
populateMetric(&values, ctx, Stat::e_CONFIRM_TIME_MAX);
}

inline void
JsonPrinterImpl::populateQueueStats(bdljsn::JsonObject* domainObject,
const mwcst::StatContext& ctx) const
JsonPrinterImpl::populateOneDomainStats(bdljsn::JsonObject* domainObject,
const mwcst::StatContext& ctx)
{
// PRECONDITIONS
BSLS_ASSERT_SAFE(domainObject);
Expand All @@ -171,7 +174,7 @@ JsonPrinterImpl::populateQueueStats(bdljsn::JsonObject* domainObject,
++queueIt) {
bdljsn::JsonObject& queueObj =
(*domainObject)[queueIt->name()].makeObject();
populateQueueValues(&queueObj, *queueIt);
populateQueueStats(&queueObj, *queueIt);

if (queueIt->numSubcontexts() > 0) {
bdljsn::JsonObject& appIdsObject = queueObj["appIds"].makeObject();
Expand All @@ -184,17 +187,16 @@ JsonPrinterImpl::populateQueueStats(bdljsn::JsonObject* domainObject,
// Do not expect another nested StatContext within appId
BSLS_ASSERT_SAFE(0 == appIdIt->numSubcontexts());

populateQueueValues(
&appIdsObject[appIdIt->name()].makeObject(),
*appIdIt);
populateQueueStats(&appIdsObject[appIdIt->name()].makeObject(),
*appIdIt);
}
}
}
}

inline void
JsonPrinterImpl::populateDomainQueueStats(bdljsn::JsonObject* parent,
const mwcst::StatContext& ctx) const
JsonPrinterImpl::populateAllDomainsStats(bdljsn::JsonObject* parent,
const mwcst::StatContext& ctx)
{
// PRECONDITIONS
BSLS_ASSERT_SAFE(parent);
Expand All @@ -203,7 +205,8 @@ JsonPrinterImpl::populateDomainQueueStats(bdljsn::JsonObject* parent,
for (mwcst::StatContextIterator domainIt = ctx.subcontextIterator();
domainIt;
++domainIt) {
populateQueueStats(&nodes[domainIt->name()].makeObject(), *domainIt);
populateOneDomainStats(&nodes[domainIt->name()].makeObject(),
*domainIt);
}
}

Expand All @@ -222,15 +225,15 @@ inline int JsonPrinterImpl::printStats(bsl::string* out, bool compact) const
*d_contexts.find("domainQueues")->second;
bdljsn::JsonObject& domainQueuesObj = obj["domainQueues"].makeObject();

populateDomainQueueStats(&domainQueuesObj, ctx);
populateAllDomainsStats(&domainQueuesObj, ctx);
}

const bdljsn::WriteOptions& ops = compact ? d_opsCompact : d_opsPretty;

mwcu::MemOutStream os;
const int rc = bdljsn::JsonUtil::write(os, json, ops);
if (0 != rc) {
BALL_LOG_ERROR << "failed to encode stats json, rc = " << rc;
BALL_LOG_ERROR << "Failed to encode stats JSON, rc = " << rc;
return rc; // RETURN
}
(*out) = os.str();
Expand All @@ -243,14 +246,13 @@ inline int JsonPrinterImpl::printStats(bsl::string* out, bool compact) const
// class JsonPrinter
// -----------------

JsonPrinter::JsonPrinter(const mqbcfg::StatsConfig& config,
const StatContextsMap& statContextsMap,
bslma::Allocator* allocator)
: d_allocator_p(bslma::Default::allocator(allocator))
, d_impl_mp(new (*d_allocator_p)
JsonPrinterImpl(config, statContextsMap, d_allocator_p),
d_allocator_p)
JsonPrinter::JsonPrinter(const StatContextsMap& statContextsMap,
bslma::Allocator* allocator)
{
bslma::Allocator* alloc = bslma::Default::allocator(allocator);

d_impl_mp.load(new (*alloc) JsonPrinterImpl(statContextsMap, alloc),
alloc);
}

int JsonPrinter::printStats(bsl::string* out, bool compact) const
Expand Down
41 changes: 14 additions & 27 deletions src/groups/mqb/mqbstat/mqbstat_jsonprinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,23 @@
#ifndef INCLUDED_MQBSTAT_JSONPRINTER
#define INCLUDED_MQBSTAT_JSONPRINTER

//@PURPOSE: Provide a mechanism to print statistics as a json
//@PURPOSE: Provide a mechanism to print statistics as a JSON
//
//@CLASSES:
// mqbstat::JsonPrinter: statistics printer to json
// mqbstat::JsonPrinter: statistics printer to JSON
//
//@DESCRIPTION: 'mqbstat::JsonPrinter' handles the printing of the statistics
// as a compact or pretty json. It is responsible solely for printing, so any
// as a compact or pretty JSON. It is responsible solely for printing, so any
// statistics updates (e.g. making a new snapshot of the used StatContexts)
// must be done before calling to this component.

// MQB
#include <mqbcfg_messages.h>

// MWC
#include <mwcst_statcontext.h>

// BDE
#include <bsl_string.h>
#include <bsl_unordered_map.h>
#include <bslma_allocator.h>
#include <bslma_usesbslmaallocator.h>
#include <bslmf_nestedtraitdeclaration.h>

namespace BloombergLP {

Expand All @@ -54,41 +49,33 @@ class JsonPrinterImpl;
// =================

class JsonPrinter {
private:
// PRIVATE TYPES
typedef bsl::unordered_map<bsl::string, mwcst::StatContext*>
StatContextsMap;

private:
// DATA
/// Allocator to use
bslma::Allocator* d_allocator_p;

/// Managed pointer to the printer implementation.
const bslma::ManagedPtr<JsonPrinterImpl> d_impl_mp;
bslma::ManagedPtr<JsonPrinterImpl> d_impl_mp;

private:
// NOT IMPLEMENTED
JsonPrinter(const JsonPrinter& other) BSLS_CPP11_DELETED;
JsonPrinter& operator=(const JsonPrinter& other) BSLS_CPP11_DELETED;

public:
// TRAITS
BSLMF_NESTED_TRAIT_DECLARATION(JsonPrinter, bslma::UsesBslmaAllocator)
// PUBLIC TYPES
typedef bsl::unordered_map<bsl::string, mwcst::StatContext*>
StatContextsMap;

// CREATORS

/// Create a new `JsonPrinter` object, using the specified `config`,
/// `statContextsMap` and the specified `allocator`.
JsonPrinter(const mqbcfg::StatsConfig& config,
const StatContextsMap& statContextsMap,
bslma::Allocator* allocator);
/// Create a new `JsonPrinter` object, using the specified
/// `statContextsMap` and the optionally specified `allocator`.
explicit JsonPrinter(const StatContextsMap& statContextsMap,
bslma::Allocator* allocator = 0);

// ACCESSORS

/// Print the json-encoded stats to the specified `out`.
/// If the specified `compact` flag is `true`, the json is printed in
/// compact form, otherwise the json is printed in pretty form.
/// Print the JSON-encoded stats to the specified `out`.
/// If the specified `compact` flag is `true`, the JSON is printed in
/// compact form, otherwise the JSON is printed in pretty form.
/// Return `0` on success, and non-zero return code on failure.
///
/// THREAD: This method is called in the *StatController scheduler* thread.
Expand Down
8 changes: 4 additions & 4 deletions src/groups/mqb/mqbstat/mqbstat_printer.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ class Printer {
/// Create a new `Printer` object, using the specified `config`,
/// `eventScheduler`, `statContextsMap` and the specified `allocator`
/// for memory allocation.
Printer(const mqbcfg::StatsConfig& config,
bdlmt::EventScheduler* eventScheduler,
const StatContextsMap& statContextsMap,
bslma::Allocator* allocator);
explicit Printer(const mqbcfg::StatsConfig& config,
bdlmt::EventScheduler* eventScheduler,
const StatContextsMap& statContextsMap,
bslma::Allocator* allocator);

// MANIPULATORS

Expand Down
3 changes: 3 additions & 0 deletions src/groups/mqb/mqbstat/mqbstat_queuestats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ QueueStatsDomain::getValue(const mwcst::StatContext& context,
{
// invoked from the SNAPSHOT thread

// PRECONDITIONS
BSLS_ASSERT_SAFE(snapshotId >= -1); // do not support other negatives yet

const mwcst::StatValue::SnapshotLocation latestSnapshot(0, 0);

#define OLDEST_SNAPSHOT(STAT) \
Expand Down
4 changes: 2 additions & 2 deletions src/groups/mqb/mqbstat/mqbstat_queuestats.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ class QueueStatsDomain {
/// represented by its associated specified `context` as the difference
/// between the latest snapshot-ed value (i.e., `snapshotId == 0`) and
/// the value that was recorded at the specified `snapshotId` snapshots
/// ago. Any negative `snapshotId` means that the oldest available
/// snapshot should be used.
/// ago. The negative `snapshotId == -1` means that the oldest available
/// snapshot should be used, while other negative values are not supported.
///
/// THREAD: This method can only be invoked from the `snapshot` thread.
static bsls::Types::Int64 getValue(const mwcst::StatContext& context,
Expand Down
Loading

0 comments on commit 50b6ccf

Please sign in to comment.