Skip to content
Permalink
Browse files

stat: Start to improve stat collection

  • Loading branch information...
sconemad committed Aug 16, 2019
1 parent a4ca4c0 commit 6dfeeb31e4093502c925771239ba6b4b763653c4
Showing with 166 additions and 103 deletions.
  1. +97 −32 stat/StatChannel.cpp
  2. +51 −11 stat/StatChannel.h
  3. +0 −50 stat/StatModule.cpp
  4. +15 −8 stat/StatStream.cpp
  5. +3 −2 stat/StatStream.h
@@ -24,44 +24,120 @@ Free Software Foundation, Inc.,
#include "StatModule.h"
#include <sconex/ScriptTypes.h>


static const char* statTypeNames[] =
{"connections", "reads", "writes", "errors", "bytesRead", "bytesWritten"};

//=========================================================================
StatChannel::StatChannel(StatModule* module, const std::string& name)
: m_module(module),
m_name(name)
const char* Stats::stat_name(Type type)
{

if (type >= StatTypeMax) return "";
return statTypeNames[type];
}

//=========================================================================
StatChannel::~StatChannel()
Stats::Stats()
: m_stats((int)StatTypeMax, 0)
{

}

//=========================================================================
void StatChannel::inc_stat(const std::string& type, long value)
void Stats::inc_stat(Type type, long value)
{
if (type >= StatTypeMax) return;
m_stats[type] += value;
}

//=============================================================================
long Stats::get_stat(Type type) const
{
if (type >= StatTypeMax) return 0;
return m_stats[type];
}

//=============================================================================
void Stats::clear()
{
for (int i=0; i<StatTypeMax; ++i) m_stats[i] = 0;
}

//=============================================================================
std::string Stats::get_string() const
{
return "stats";
}

//=============================================================================
scx::ScriptRef* Stats::script_op(const scx::ScriptAuth& auth,
const scx::ScriptRef& ref,
const scx::ScriptOp& op,
const scx::ScriptRef* right)
{
if (m_stats.count(type) == 0) {
m_stats[type] = value;
} else {
m_stats[type] += value;
if (op.type() == scx::ScriptOp::Lookup) {
const std::string name = right->object()->get_string();

// Methods
if ("clear" == name) {
return new scx::ScriptMethodRef(ref,name);
}

// Properties
for (int t=0; t<StatTypeMax; ++t) {
if (name == stat_name((Type)t)) {
return scx::ScriptInt::new_ref(m_stats[t]);
}
}
}

return scx::ScriptObject::script_op(auth,ref,op,right);
}

//=============================================================================
long StatChannel::get_stat(const std::string& type) const
scx::ScriptRef* Stats::script_method(const scx::ScriptAuth& auth,
const scx::ScriptRef& ref,
const std::string& name,
const scx::ScriptRef* args)
{
StatMap::const_iterator it = m_stats.find(type);
if (it != m_stats.end()) {
return it->second;
if (!auth.admin()) return scx::ScriptError::new_ref("Not permitted");

if ("clear" == name) {
// Should check non-const ref
clear();
return 0;
}
return 0;

return scx::ScriptObject::script_method(auth,ref,name,args);
}

// --- StatChannel ---


//=========================================================================
StatChannel::StatChannel(StatModule* module, const std::string& name)
: m_module(module),
m_name(name),
m_stats(new Stats())
{

}

//=========================================================================
StatChannel::~StatChannel()
{

}

//=============================================================================
const Stats* StatChannel::get_stats() const
{
return m_stats.object();
}

//=============================================================================
void StatChannel::clear()
void StatChannel::inc_stat(Stats::Type type, long value)
{
m_stats.clear();
m_stats.object()->inc_stat(type, value);
}

//=============================================================================
@@ -85,22 +161,11 @@ scx::ScriptRef* StatChannel::script_op(const scx::ScriptAuth& auth,
}

// Properties
if ("list" == name) {
scx::ScriptMap* list = new scx::ScriptMap();
for (StatMap::const_iterator it = m_stats.begin();
it != m_stats.end();
++it) {
list->give(it->first,scx::ScriptInt::new_ref(it->second));
}
return new scx::ScriptRef(list);
}

StatMap::const_iterator it = m_stats.find(name);
if (it != m_stats.end()) {
return scx::ScriptInt::new_ref(it->second);
if ("totals" == name) {
return m_stats.ref_copy(ref.reftype());
}
}

return scx::ScriptObject::script_op(auth,ref,op,right);
}

@@ -113,7 +178,7 @@ scx::ScriptRef* StatChannel::script_method(const scx::ScriptAuth& auth,
if (!auth.admin()) return scx::ScriptError::new_ref("Not permitted");

if ("clear" == name) {
clear();
m_stats.object()->clear();
return 0;
}

@@ -29,23 +29,66 @@ Free Software Foundation, Inc.,
class StatModule;

//=============================================================================
// StatChannel - A statistic-collection channel
// Stats - A set of connection statistics
//
class StatChannel : public scx::ScriptObject {
class Stats : public scx::ScriptObject {
public:

StatChannel(StatModule* module, const std::string& name);
~StatChannel();
enum Type {
Connections = 0,
Reads,
Writes,
Errors,
BytesRead,
BytesWritten,
StatTypeMax
};

static const char* stat_name(Type type);

Stats();

// Increment the named stat type by value
void inc_stat(const std::string& type, long value);
void inc_stat(Type type, long value);

// Get the named stat value
long get_stat(const std::string& type) const;
long get_stat(Type type) const;

// Clear stats
void clear();


// ScriptObject methods
virtual std::string get_string() const;

virtual scx::ScriptRef* script_op(const scx::ScriptAuth& auth,
const scx::ScriptRef& ref,
const scx::ScriptOp& op,
const scx::ScriptRef* right=0);

virtual scx::ScriptRef* script_method(const scx::ScriptAuth& auth,
const scx::ScriptRef& ref,
const std::string& name,
const scx::ScriptRef* args);

typedef scx::ScriptRefTo<Stats> Ref;

private:
std::vector<long> m_stats;
};


//=============================================================================
// StatChannel - A statistic-collection channel
//
class StatChannel : public scx::ScriptObject {
public:

StatChannel(StatModule* module, const std::string& name);
~StatChannel();

const Stats* get_stats() const;
void inc_stat(Stats::Type type, long value);

// ScriptObject methods
virtual std::string get_string() const;

@@ -68,10 +111,7 @@ class StatChannel : public scx::ScriptObject {
scx::ScriptRefTo<StatModule> m_module;

std::string m_name;

typedef HASH_TYPE<std::string,long> StatMap;
StatMap m_stats;

Stats::Ref m_stats;
};

#endif
@@ -177,56 +177,6 @@ scx::ScriptRef* StatModule::script_method(const scx::ScriptAuth& auth,
}
return 0;
}

if ("print" == name) {
const scx::ScriptList* argl =
dynamic_cast<const scx::ScriptList*>(args->object());
scx::ScriptList default_argl;
if (!argl || argl->size() == 0) {
// Use these types as default if none were given
default_argl.give(scx::ScriptString::new_ref("conn"));
default_argl.give(scx::ScriptString::new_ref("in"));
default_argl.give(scx::ScriptString::new_ref("out"));
argl = &default_argl;
}

int wc = 14;
int ws = 8;
std::ostringstream oss;
// Heading
oss << "\n"
<< std::right
<< std::setw(wc)
<< "CHANNEL" << " | ";
for (int i=0; i<argl->size(); ++i) {
const scx::ScriptRef* type = argl->get(i);
oss << std::left
<< std::setw(ws)
<< type->object()->get_string() << " ";
}
oss << "\n";

// Stats
for (ChannelMap::const_iterator it = m_channels.begin();
it != m_channels.end();
++it) {

StatChannel* channel = (*it).second->object();
oss << std::right
<< std::setw(wc)
<< (*it).first << " | ";
for (int i=0; i<argl->size(); ++i) {
const scx::ScriptRef* type = argl->get(i);
long stat = channel->get_stat(type->object()->get_string());
oss << std::left
<< std::setw(ws)
<< stat << " ";
}
oss << "\n";
}
return scx::ScriptString::new_ref(oss.str());
}

return scx::Module::script_method(auth,ref,name,args);
}

@@ -32,9 +32,10 @@ StatStream::StatStream(StatModule* module,
StatChannel* channel)
: scx::Stream("stat"),
m_module(module),
m_channel(channel)
m_channel(channel),
m_stats(new Stats())
{
inc_stat("conn",1);
inc_stat(Stats::Connections, 1);
}

//=========================================================================
@@ -47,15 +48,17 @@ StatStream::~StatStream()
scx::Condition StatStream::read(void* buffer,int n,int& na)
{
scx::Condition c = Stream::read(buffer,n,na);
inc_stat("in",na);
inc_stat(c == scx::Error ? Stats::Errors : Stats::Reads, 1);
inc_stat(Stats::BytesRead, na);
return c;
}

//=========================================================================
scx::Condition StatStream::write(const void* buffer,int n,int& na)
{
scx::Condition c = Stream::write(buffer,n,na);
inc_stat("out",na);
inc_stat(c == scx::Error ? Stats::Errors : Stats::Writes, 1);
inc_stat(Stats::BytesWritten, na);
return c;
}

@@ -64,15 +67,19 @@ std::string StatStream::stream_status() const
{
std::ostringstream oss;
oss << m_channel.object()->get_string();
oss << " conn:" << m_channel.object()->get_stat("conn");
oss << " in:" << m_channel.object()->get_stat("in");
oss << " out:" << m_channel.object()->get_stat("out");
oss << " r:" << m_stats.object()->get_stat(Stats::Reads) << "("
<< m_stats.object()->get_stat(Stats::BytesRead) << ")";
oss << " w:" << m_stats.object()->get_stat(Stats::Writes) << "("
<< m_stats.object()->get_stat(Stats::BytesWritten) << ")";
oss << " e:" << m_stats.object()->get_stat(Stats::Errors);
return oss.str();
}

//=========================================================================
void StatStream::inc_stat(const std::string& type, long value)
void StatStream::inc_stat(Stats::Type type, long value)
{
if (type >= Stats::StatTypeMax) return;
m_stats.object()->inc_stat(type, value);
m_channel.object()->inc_stat(type,value);
}

@@ -48,10 +48,11 @@ class StatStream : public scx::Stream {

private:

void inc_stat(const std::string& type, long value);
void inc_stat(Stats::Type type, long value);

StatModule::Ref m_module;
StatChannel::Ref m_channel;
StatChannel::Ref m_channel;
Stats::Ref m_stats;
};

#endif

0 comments on commit 6dfeeb3

Please sign in to comment.
You can’t perform that action at this time.