Add: track savegame size to report with survey (#12304)

This commit is contained in:
Patric Stout 2024-03-16 08:58:56 +01:00 committed by GitHub
parent b394c20519
commit 3e625b5b1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 48 additions and 17 deletions

View File

@ -102,6 +102,10 @@ void CrashLog::FillCrashLog()
this->survey["stacktrace"] = "crashed while gathering information";
}
if (!this->TryExecute("session", [this]() { SurveyGameSession(this->survey["session"]); return true; })) {
this->survey["session"] = "crashed while gathering information";
}
{
auto &info = this->survey["info"];
if (!this->TryExecute("os", [&info]() { SurveyOS(info["os"]); return true; })) {

View File

@ -46,8 +46,8 @@ bool _screen_disable_anim = false; ///< Disable palette animation (important f
std::atomic<bool> _exit_game;
GameMode _game_mode;
SwitchMode _switch_mode; ///< The next mainloop command.
std::chrono::steady_clock::time_point _switch_mode_time; ///< The time when the switch mode was requested.
PauseMode _pause_mode;
GameSessionStats _game_session_stats; ///< Statistics about the current session.
static byte _stringwidth_table[FS_END][224]; ///< Cache containing width of often used characters. @see GetCharacterWidth()
DrawPixelInfo *_cur_dpi;

View File

@ -36,8 +36,6 @@
#include "safeguards.h"
std::string _savegame_id; ///< Unique ID of the current savegame.
extern TileIndex _cur_tileloop_tile;
extern void MakeNewgameSettingsLive();
@ -89,7 +87,7 @@ std::string GenerateUid(std::string_view subject)
*/
void GenerateSavegameId()
{
_savegame_id = GenerateUid("OpenTTD Savegame ID");
_game_session_stats.savegame_id = GenerateUid("OpenTTD Savegame ID");
}
void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settings)

View File

@ -48,7 +48,7 @@ static const size_t COMPAT_MTU = 1460; ///< Number of bytes we can pack in a sin
static const byte NETWORK_GAME_ADMIN_VERSION = 3; ///< What version of the admin network do we use?
static const byte NETWORK_GAME_INFO_VERSION = 7; ///< What version of game-info do we use?
static const byte NETWORK_COORDINATOR_VERSION = 6; ///< What version of game-coordinator-protocol do we use?
static const byte NETWORK_SURVEY_VERSION = 1; ///< What version of the survey do we use?
static const byte NETWORK_SURVEY_VERSION = 2; ///< What version of the survey do we use?
static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0'
static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0'

View File

@ -882,7 +882,8 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
SendMapOk();
/* As we skipped switch-mode, update the time we "switched". */
_switch_mode_time = std::chrono::steady_clock::now();
_game_session_stats.start_time = std::chrono::steady_clock::now();
_game_session_stats.savegame_size = std::nullopt;
ShowClientList();

View File

@ -19,8 +19,6 @@
#include "../safeguards.h"
extern std::string _savegame_id;
NetworkSurveyHandler _survey = {};
NLOHMANN_JSON_SERIALIZE_ENUM(NetworkSurveyHandler::Reason, {
@ -43,7 +41,6 @@ std::string NetworkSurveyHandler::CreatePayload(Reason reason, bool for_preview)
survey["schema"] = NETWORK_SURVEY_VERSION;
survey["reason"] = reason;
survey["id"] = _savegame_id;
survey["date"] = fmt::format("{:%Y-%m-%d %H:%M:%S} (UTC)", fmt::gmtime(time(nullptr)));
#ifdef SURVEY_KEY
@ -53,6 +50,8 @@ std::string NetworkSurveyHandler::CreatePayload(Reason reason, bool for_preview)
survey["key"] = "";
#endif
SurveyGameSession(survey["session"]);
{
auto &info = survey["info"];
SurveyOS(info["os"]);

View File

@ -517,7 +517,8 @@ static const OptionData _options[] = {
*/
int openttd_main(int argc, char *argv[])
{
_switch_mode_time = std::chrono::steady_clock::now();
_game_session_stats.start_time = std::chrono::steady_clock::now();
_game_session_stats.savegame_size = std::nullopt;
std::string musicdriver;
std::string sounddriver;
@ -1086,7 +1087,10 @@ void SwitchToMode(SwitchMode new_mode)
if (_game_mode == GM_NORMAL && new_mode != SM_SAVE_GAME) _survey.Transmit(NetworkSurveyHandler::Reason::LEAVE);
/* Keep track when we last switch mode. Used for survey, to know how long someone was in a game. */
if (new_mode != SM_SAVE_GAME) _switch_mode_time = std::chrono::steady_clock::now();
if (new_mode != SM_SAVE_GAME) {
_game_session_stats.start_time = std::chrono::steady_clock::now();
_game_session_stats.savegame_size = std::nullopt;
}
switch (new_mode) {
case SM_EDITOR: // Switch to scenario editor

View File

@ -52,9 +52,15 @@ enum DisplayOptions {
DO_SHOW_COMPETITOR_SIGNS = 7, ///< Display signs, station names and waypoint names of opponent companies. Buoys and oilrig-stations are always shown, even if this option is turned off.
};
struct GameSessionStats {
std::chrono::steady_clock::time_point start_time; ///< Time when the current game was started.
std::string savegame_id; ///< Unique ID of the savegame.
std::optional<size_t> savegame_size; ///< Size of the last saved savegame in bytes, or std::nullopt if not saved yet.
};
extern GameMode _game_mode;
extern SwitchMode _switch_mode;
extern std::chrono::steady_clock::time_point _switch_mode_time;
extern GameSessionStats _game_session_stats;
extern std::atomic<bool> _exit_game;
extern bool _save_config;

View File

@ -29,7 +29,6 @@
extern TileIndex _cur_tileloop_tile;
extern uint16_t _disaster_delay;
extern byte _trees_tick_ctr;
extern std::string _savegame_id;
/* Keep track of current game position */
int _saved_scrollpos_x;
@ -98,7 +97,7 @@ static const SaveLoad _date_desc[] = {
SLEG_VAR("company_tick_counter", _cur_company_tick_index, SLE_FILE_U8 | SLE_VAR_U32),
SLEG_VAR("trees_tick_counter", _trees_tick_ctr, SLE_UINT8),
SLEG_CONDVAR("pause_mode", _pause_mode, SLE_UINT8, SLV_4, SL_MAX_VERSION),
SLEG_CONDSSTR("id", _savegame_id, SLE_STR, SLV_SAVEGAME_ID, SL_MAX_VERSION),
SLEG_CONDSSTR("id", _game_session_stats.savegame_id, SLE_STR, SLV_SAVEGAME_ID, SL_MAX_VERSION),
/* For older savegames, we load the current value as the "period"; afterload will set the "fired" and "elapsed". */
SLEG_CONDVAR("next_competitor_start", _new_competitor_timeout.period, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_109),
SLEG_CONDVAR("next_competitor_start", _new_competitor_timeout.period, SLE_UINT32, SLV_109, SLV_AI_START_DATE),

View File

@ -2182,7 +2182,10 @@ struct FileReader : LoadFilter {
/** Make sure everything is cleaned up. */
~FileReader()
{
if (this->file != nullptr) fclose(this->file);
if (this->file != nullptr) {
_game_session_stats.savegame_size = ftell(this->file) - this->begin;
fclose(this->file);
}
this->file = nullptr;
}
@ -2231,7 +2234,10 @@ struct FileWriter : SaveFilter {
void Finish() override
{
if (this->file != nullptr) fclose(this->file);
if (this->file != nullptr) {
_game_session_stats.savegame_size = ftell(this->file);
fclose(this->file);
}
this->file = nullptr;
}
};

View File

@ -235,6 +235,20 @@ void SurveyOpenTTD(nlohmann::json &survey)
;
}
/**
* Convert game session information to JSON.
*
* @param survey The JSON object.
*/
void SurveyGameSession(nlohmann::json &survey)
{
survey["id"] = _game_session_stats.savegame_id;
survey["seconds"] = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - _game_session_stats.start_time).count();
if (_game_session_stats.savegame_size.has_value()) {
survey["savegame_size"] = _game_session_stats.savegame_size.value();
}
}
/**
* Convert generic game information to JSON.
*
@ -330,7 +344,6 @@ void SurveyCompanies(nlohmann::json &survey)
void SurveyTimers(nlohmann::json &survey)
{
survey["ticks"] = TimerGameTick::counter;
survey["seconds"] = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - _switch_mode_time).count();
TimerGameEconomy::YearMonthDay economy_ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
survey["economy"] = fmt::format("{:04}-{:02}-{:02} ({})", economy_ymd.year, economy_ymd.month + 1, economy_ymd.day, TimerGameEconomy::date_fract);

View File

@ -16,6 +16,7 @@ std::string SurveyMemoryToText(uint64_t memory);
void SurveyCompanies(nlohmann::json &survey);
void SurveyCompiler(nlohmann::json &survey);
void SurveyGameSession(nlohmann::json &survey);
void SurveyConfiguration(nlohmann::json &survey);
void SurveyFont(nlohmann::json &survey);
void SurveyGameScript(nlohmann::json &survey);