mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-15 08:47:56 +01:00
new stats module gathering data for debugging and upload (soon)
This commit is contained in:
parent
72082cde0d
commit
4ab6b1930f
13 changed files with 169 additions and 26 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
@ -184,7 +184,7 @@ void dutil_super_cleanup( XW_DUtilCtxt* dutil, XWEnv xwe );
|
|||
#define dutil_notifyPause( duc, e, id, ip, p, n, m ) \
|
||||
(duc)->vtable.m_dutil_notifyPause( (duc), (e), (id), (ip), (p), (n), (m) )
|
||||
|
||||
#define dutil_haveGame( duc, xwe, gameID,channel ) \
|
||||
#define dutil_haveGame( duc, xwe, gameID, channel ) \
|
||||
(duc)->vtable.m_dutil_haveGame( (duc), (xwe), (gameID), (channel) )
|
||||
|
||||
#define dutil_onDupTimerChanged(duc, e, id, ov, nv) \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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( ¶ms->dutil );
|
||||
vtmgr_destroy( MPPARM(params->mpool) params->vtMgr );
|
||||
dmgr_destroy( params->dictMgr, NULL_XWE );
|
||||
|
||||
gi_disposePlayerInfo( MPPARM(params->mpool) ¶ms->pgi );
|
||||
|
||||
gdb_close( params->pDb );
|
||||
params->pDb = NULL;
|
||||
|
||||
mpool_destroy( params->mpool );
|
||||
}
|
||||
|
||||
|
|
|
@ -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] );
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Add table
Reference in a new issue