new stats module gathering data for debugging and upload (soon)

This commit is contained in:
Eric House 2024-08-07 08:01:48 -07:00
parent 72082cde0d
commit 4ab6b1930f
13 changed files with 169 additions and 26 deletions

View file

@ -1092,7 +1092,7 @@ makeDUtil( MPFORMAL JNIEnv* env,
{
AndDUtil* dutil = (AndDUtil*)XP_CALLOC( mpool, sizeof(*dutil) );
XW_DUtilCtxt* super = &dutil->dutil;
dutil_super_init( MPPARM(mpool) super, env );
dutil_super_init( MPPARM(mpool) super );
#ifdef MAP_THREAD_TO_ENV
dutil->ti = ti;
#endif

View file

@ -259,6 +259,7 @@ typedef enum _TileValueType {
#define SUFFIX_LEGAL_PHONIES "legalPhonies"
#define SUFFIX_MQTT_DEVID "mqtt_devid_key"
#define SUFFIX_KNOWN_PLAYERS "known_players_key_dev1"
#define SUFFIX_STATS "stats_key_dev1"
#define FULL_KEY(PARTIAL) "persist_key:" PARTIAL
@ -268,6 +269,7 @@ typedef enum _TileValueType {
#define KEY_LEGAL_PHONIES FULL_KEY(SUFFIX_LEGAL_PHONIES)
#define MQTT_DEVID_KEY FULL_KEY(SUFFIX_MQTT_DEVID)
#define KNOWN_PLAYERS_KEY FULL_KEY(SUFFIX_KNOWN_PLAYERS)
#define STATS_KEY FULL_KEY(SUFFIX_STATS)
/* I need a way to communiate prefs to common/ code. For now, though, I'll
* leave storage of these values up to the platforms. First, because I don't

View file

@ -41,7 +41,7 @@
#define PD_VERSION_1 2
static XWStreamCtxt*
XWStreamCtxt*
mkStream( XW_DUtilCtxt* dutil )
{
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(dutil->mpool)

View file

@ -81,4 +81,7 @@ void dvc_getPhoniesFor( XW_DUtilCtxt* dutil, XWEnv env, const XP_UCHAR* code,
void dvc_init( XW_DUtilCtxt* dutil, XWEnv xwe );
void dvc_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe );
/* Utility functions; not an API to count on!! */
XWStreamCtxt* mkStream( XW_DUtilCtxt* dutil );
#endif

View file

@ -55,7 +55,7 @@ super_dutil_loadStream( XW_DUtilCtxt* duc, XWEnv xwe,
}
void
dutil_super_init( MPFORMAL XW_DUtilCtxt* dutil, XWEnv xwe )
dutil_super_init( MPFORMAL XW_DUtilCtxt* dutil )
{
#ifdef XWFEATURE_KNOWNPLAYERS
pthread_mutex_init( &dutil->kpMutex, NULL );
@ -66,13 +66,13 @@ dutil_super_init( MPFORMAL XW_DUtilCtxt* dutil, XWEnv xwe )
SET_VTABLE_ENTRY( &dutil->vtable, dutil_loadStream, super );
SET_VTABLE_ENTRY( &dutil->vtable, dutil_storeStream, super );
sts_init( dutil, xwe );
sts_init( dutil );
}
void
dutil_super_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe )
{
kplr_cleanup( dutil );
sts_cleanup( dutil );
sts_cleanup( dutil, xwe );
dvc_cleanup( dutil, xwe );
}

View file

@ -129,7 +129,7 @@ struct XW_DUtilCtxt {
MPSLOT
};
void dutil_super_init( MPFORMAL XW_DUtilCtxt* dutil, XWEnv xwe );
void dutil_super_init( MPFORMAL XW_DUtilCtxt* dutil );
void dutil_super_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe );
/* This one cheats: direct access */

View file

@ -18,30 +18,70 @@
*/
#include "stats.h"
#include "xwmutex.h"
#include "device.h"
#include "xwstream.h"
#include "strutils.h"
typedef struct StatsState {
// XP_U32 stats[STS_KEY_COUNT];
XP_U32* statsVals;
pthread_mutex_t mutex;
} StatsState;
static const XP_UCHAR* STATtoStr(STAT stat);
static XP_U32* loadCounts( XW_DUtilCtxt* dutil, XWEnv xwe );
static void storeCounts( XW_DUtilCtxt* dutil, XWEnv xwe );
void
sts_init( XW_DUtilCtxt* duc, XWEnv XP_UNUSED(xwe) )
sts_init( XW_DUtilCtxt* dutil )
{
LOG_FUNC();
StatsState* ss = XP_CALLOC( duc->mpool, sizeof(*ss) );
duc->statsState = ss;
StatsState* ss = XP_CALLOC( dutil->mpool, sizeof(*ss) );
initMutex( &ss->mutex, XP_TRUE );
dutil->statsState = ss;
}
void
sts_cleanup( XW_DUtilCtxt* dutil )
sts_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe )
{
XP_USE( dutil );
XP_FREEP( dutil->mpool, &dutil->statsState );
StatsState* ss = dutil->statsState;
storeCounts( dutil, xwe );
XP_ASSERT( !!ss );
XP_FREEP( dutil->mpool, &ss->statsVals );
XP_FREEP( dutil->mpool, &ss );
}
void
sts_increment( XW_DUtilCtxt* dutil, STAT stat, XWEnv xwe )
{
StatsState* ss = dutil->statsState;
XP_ASSERT( !!ss );
WITH_MUTEX( &ss->mutex );
if ( !ss->statsVals ) {
ss->statsVals = loadCounts( dutil, xwe );
}
++ss->statsVals[stat];
END_WITH_MUTEX();
}
cJSON*
sts_export( XW_DUtilCtxt* XP_UNUSED(dutil), XWEnv XP_UNUSED(xwe) )
sts_export( XW_DUtilCtxt* dutil, XWEnv xwe )
{
StatsState* ss = dutil->statsState;
XP_ASSERT( !!ss );
cJSON* result = cJSON_CreateObject();
WITH_MUTEX( &ss->mutex );
if ( !ss->statsVals ) {
ss->statsVals = loadCounts( dutil, xwe );
}
for ( int ii = 0; ii < STAT_NSTATS; ++ii ) {
XP_U32 val = ss->statsVals[ii];
if ( 0 != val ) {
const XP_UCHAR* nam = STATtoStr(ii);
cJSON_AddNumberToObject(result, nam, val);
}
}
END_WITH_MUTEX();
return result;
}
@ -56,3 +96,66 @@ void
sts_clearAll( XW_DUtilCtxt* XP_UNUSED(dutil), XWEnv XP_UNUSED(xwe) )
{
}
static const XP_UCHAR*
STATtoStr(STAT stat)
{
#define CASESTR(s) case (s): return #s
switch (stat) {
CASESTR(STAT_MQTT_RCVD);
CASESTR(STAT_MQTT_SENT);
default:
XP_ASSERT(0);
}
#undef CASESTR
return NULL;
}
static void
storeCounts( XW_DUtilCtxt* dutil, XWEnv xwe )
{
StatsState* ss = dutil->statsState;
XP_ASSERT( !!ss );
XWStreamCtxt* stream = mkStream( dutil );
stream_putU8( stream, 0 ); /* version */
WITH_MUTEX( &ss->mutex );
if ( !!ss->statsVals ) {
for ( int ii = 0; ii < STAT_NSTATS; ++ii ) {
XP_U32 val = ss->statsVals[ii];
if ( 0 != val ) {
stream_putU8( stream, ii );
stream_putU32VL( stream, val );
}
}
}
END_WITH_MUTEX();
const XP_UCHAR* keys[] = { STATS_KEY, NULL };
dutil_storeStream( dutil, xwe, keys, stream );
stream_destroy( stream );
}
static XP_U32*
loadCounts( XW_DUtilCtxt* dutil, XWEnv xwe )
{
XWStreamCtxt* stream = mkStream( dutil );
const XP_UCHAR* keys[] = { STATS_KEY, NULL };
dutil_loadStream( dutil, xwe, keys, stream );
XP_U32* statsVals
= XP_CALLOC( dutil->mpool, sizeof(*statsVals) * STAT_NSTATS );
XP_U8 version;
if ( stream_gotU8( stream, &version ) ) {
XP_U8 stat;
while ( stream_gotU8( stream, &stat ) ) {
XP_U32 value = stream_getU32VL( stream );
statsVals[stat] = value;
}
}
stream_destroy( stream );
return statsVals;
}

View file

@ -22,8 +22,18 @@
#include "dutil.h"
void sts_init( XW_DUtilCtxt* duc, XWEnv xwe );
void sts_cleanup( XW_DUtilCtxt* dutil );
void sts_init( XW_DUtilCtxt* duc );
void sts_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe );
typedef enum {
STAT_MQTT_RCVD,
STAT_MQTT_SENT,
STAT_NSTATS,
} STAT;
void sts_increment( XW_DUtilCtxt* dutil, STAT stat, XWEnv xwe );
cJSON* sts_export( XW_DUtilCtxt* duc, XWEnv xwe );
void sts_clearAll( XW_DUtilCtxt* duc, XWEnv xwe );

View file

@ -27,6 +27,7 @@
#include "linuxmain.h"
#include "gamesdb.h"
#include "dbgutil.h"
#include "stats.h"
static XP_U32
castGid( cJSON* obj )
@ -131,6 +132,14 @@ moveifFromArgs( CmdWrapper* wr, cJSON* args )
return (*wr->procs.makeMoveIf)( wr->closure, gameID, tryTrade );
}
static cJSON*
getStats( CmdWrapper* wr )
{
XW_DUtilCtxt* dutil = wr->params->dutil;
cJSON* json = sts_export( dutil, NULL_XWE );
return json;
}
static XP_Bool
chatFromArgs( CmdWrapper* wr, cJSON* args )
{
@ -418,6 +427,12 @@ on_incoming_signal( GSocketService* XP_UNUSED(service),
if ( success ) {
addGIDToObject( &response, newGameID, "newGid" );
}
} else if ( 0 == strcmp( cmdStr, "stats" ) ) {
cJSON* stats = getStats( wr );
success = !!stats;
if ( success ) {
addObjectToObject( &response, "stats", stats );
}
} else if ( 0 == strcmp( cmdStr, "getStates" ) ) {
cJSON* gids;
cJSON* orders;

View file

@ -402,8 +402,6 @@ linux_dutils_init( MPFORMAL VTableMgr* vtMgr, void* closure )
XW_DUtilCtxt* super = &lduc->super;
dutil_super_init( MPPARM(mpool) super, NULL_XWE );
super->vtMgr = vtMgr;
super->closure = closure;
@ -445,6 +443,8 @@ linux_dutils_init( MPFORMAL VTableMgr* vtMgr, void* closure )
# undef SET_PROC
dutil_super_init( MPPARM(mpool) super );
assertTableFull( &super->vtable, sizeof(super->vtable), "lindutil" );
return super;

View file

@ -2488,14 +2488,15 @@ testPhonies( LaunchParams* params )
static void
freeParams( LaunchParams* params )
{
gdb_close( params->pDb );
params->pDb = NULL;
vtmgr_destroy( MPPARM(params->mpool) params->vtMgr );
linux_dutils_free( &params->dutil );
vtmgr_destroy( MPPARM(params->mpool) params->vtMgr );
dmgr_destroy( params->dictMgr, NULL_XWE );
gi_disposePlayerInfo( MPPARM(params->mpool) &params->pgi );
gdb_close( params->pDb );
params->pDb = NULL;
mpool_destroy( params->mpool );
}

View file

@ -24,6 +24,7 @@
#include "gsrcwrap.h"
#include "device.h"
#include "strutils.h"
#include "stats.h"
typedef struct _MQTTConStorage {
LaunchParams* params;
@ -60,6 +61,7 @@ sendQueueHead( MQTTConStorage* storage )
XP_LOGFF( "mosquitto_publish(topic=%s, msgLen=%d) => %s; mid=%d", elem->topic,
elem->len, mosquitto_strerror(err), elem->mid );
/* Remove this so all are resent together? */
sts_increment( storage->params->dutil, STAT_MQTT_SENT, NULL_XWE );
break;
}
}
@ -293,9 +295,11 @@ log_callback( struct mosquitto *mosq, void *userdata, int level,
static gboolean
handle_gotmsg( GIOChannel* source, GIOCondition XP_UNUSED(condition), gpointer data )
{
MQTTConStorage* storage = (MQTTConStorage*)data;
// XP_LOGFF( "(len=%d)", message->payloadlen );
LOG_FUNC();
MQTTConStorage* storage = (MQTTConStorage*)data;
XW_DUtilCtxt* dutil = storage->params->dutil;
sts_increment( dutil, STAT_MQTT_RCVD, NULL_XWE );
int pipe = g_io_channel_unix_get_fd( source );
XP_ASSERT( pipe == storage->msgPipe[0] );

View file

@ -527,7 +527,12 @@ class Device():
if game and not game.haveOrder():
orders.append(gid)
response = self._sendWaitReply('getStates', gids=gids, orders=orders)
# PENDING. Don't print this, but include in summary on exit
response = self._sendWaitReply('stats')
print('stats => {}'.format(response))
response = self \
._sendWaitReply('getStates', gids=gids, orders=orders)
for order in response.get('orders', []):
gid = order.get('gid')