From 52f15961fec4e2cfbc56d4a53804276618b759ec Mon Sep 17 00:00:00 2001 From: Mondus Date: Wed, 20 Nov 2024 12:07:42 +0000 Subject: [PATCH 1/9] Added User ID to telemetry --- README.md | 2 +- include/flamegpu/io/Telemetry.h | 18 +++++++ src/flamegpu/io/Telemetry.cpp | 96 ++++++++++++++++++++++++++++++++- 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a25f4959d..d4edfd658 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,7 @@ Information is collected when a simulation, ensemble or test suite run have comp The [TelemetryDeck](https://telemetrydeck.com/) service is used to store telemetry data. All data is sent to their API endpoint of https://nom.telemetrydeck.com/v1/ via https. For more details please review the [TelmetryDeck privacy policy](https://telemetrydeck.com/privacy/). -We do not collect any personal data such as usernames, email addresses or machine identifiers. +We do not collect any personal data such as usernames, email addresses or hardware identifiers but we do generate a random user identifier. This identifier is salted and hashed by Telemetry deck. More information can be found in the [FLAMEGPU documentation](https://docs.flamegpu.com/guide/telemetry). diff --git a/include/flamegpu/io/Telemetry.h b/include/flamegpu/io/Telemetry.h index 1b6c87481..a99e39147 100644 --- a/include/flamegpu/io/Telemetry.h +++ b/include/flamegpu/io/Telemetry.h @@ -84,6 +84,24 @@ static void encourageUsage(); * @return if telemetry is currently in test mode or not. */ static bool isTestMode(); + +/** + * Gets a cross platform location for storing user configuration data. Required to store a per user Id. On windows this uses the AppData folder (CSIDL_APPDATA) and in Linux this uses XDG_CONFIG_HOME. + * @return Root directory for storing configuration files + */ +static std::string getConfigDirectory(); + +/** + * Generates a randomised 36 character alphanumeric string for use as a User Id. + * @return A 36 character randomised alphanumeric string + */ +static std::string generateRandomId(); + +/** + * Obtains a unique user Id. If a configuration file (flamegpu_user.cfg) exists this will be loaded from disk otherwise it will be generated and stored in the configuration location. If the configuration location is not writeable a new user Id will be generated each time. The user Id will be further obfuscated by Telemetry Deck which will salt and hash the Id. + * @return A 36 character randomised alphanumeric string representing a unique user Id + */ +static std::string getUserId(); }; } // namespace io } // namespace flamegpu diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index e298cb136..a37df1a18 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -6,11 +6,22 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif #include "flamegpu/version.h" @@ -159,7 +170,7 @@ std::string Telemetry::generateData(std::string event_name, std::mappw_dir) + "/.config"; + } + } + throw std::runtime_error("Unable to retrieve config directory on Linux"); +#endif +} + +std::string Telemetry::generateRandomId() { + const char charset[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const size_t length = 36; + std::random_device rd; + std::mt19937 generator(rd()); + std::uniform_int_distribution distribution(0, sizeof(charset) - 2); + + std::string randomId; + for (size_t i = 0; i < length; ++i) { + randomId += charset[distribution(generator)]; + } + return randomId; +} + +std::string Telemetry::getUserId() { + // Generate and a new random 36-character user ID + std::string userId = Telemetry::generateRandomId(); + + // Try to load an existing ID from file if it exists + try { + // Determine config file location + std::string configDir = Telemetry::getConfigDirectory() + "/FLAMEGPU"; + std::filesystem::create_directories(configDir); // Ensure the directory exists + std::string filePath = configDir + "/flamegpu_user.cfg"; + + // Check if the file exists + if (std::filesystem::exists(filePath)) { + std::ifstream file(filePath); + if (file.is_open()) { + std::getline(file, userId); // overwrite existing Id + file.close(); + return userId; // Config file and user id found so return it + } + else { + throw std::runtime_error("Unable to open user ID file for reading"); + } + } + + std::ofstream file(filePath); + if (file.is_open()) { + file << userId; + file.close(); + } + else { + throw std::runtime_error("Unable to create user ID file"); + } + } catch (const std::exception&) { + fprintf(stderr, "Warning: Telemetry User Id file is not read/writeable from config file. A new User Id will be used."); + } + return userId; +} + + } // namespace io } // namespace flamegpu From ab972a7b5fbe933ccb50e06bc494119bac99e814 Mon Sep 17 00:00:00 2001 From: Mondus Date: Wed, 20 Nov 2024 12:29:22 +0000 Subject: [PATCH 2/9] Fixed linting --- src/flamegpu/io/Telemetry.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index a37df1a18..719f17eda 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -18,7 +18,6 @@ #include #include #else -#include #include #include #endif @@ -170,7 +169,7 @@ std::string Telemetry::generateData(std::string event_name, std::mappw_dir) + "/.config"; } @@ -354,16 +353,16 @@ std::string Telemetry::getUserId() { try { // Determine config file location std::string configDir = Telemetry::getConfigDirectory() + "/FLAMEGPU"; - std::filesystem::create_directories(configDir); // Ensure the directory exists + std::filesystem::create_directories(configDir); // Ensure the directory exists std::string filePath = configDir + "/flamegpu_user.cfg"; // Check if the file exists if (std::filesystem::exists(filePath)) { std::ifstream file(filePath); if (file.is_open()) { - std::getline(file, userId); // overwrite existing Id + std::getline(file, userId); // overwrite existing Id file.close(); - return userId; // Config file and user id found so return it + return userId; // Config file and user id found so return it } else { throw std::runtime_error("Unable to open user ID file for reading"); From 8ea5fa951873fed57ec7eeaf432d5b882cc95e66 Mon Sep 17 00:00:00 2001 From: Mondus Date: Wed, 20 Nov 2024 12:43:22 +0000 Subject: [PATCH 3/9] fixing unix errors --- src/flamegpu/io/Telemetry.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index 719f17eda..a72b8e59b 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -19,6 +19,7 @@ #include #else #include +#include #include #endif From 85b59cb3f1060d8d5063410e68508b09c0e30ffd Mon Sep 17 00:00:00 2001 From: Mondus Date: Wed, 20 Nov 2024 12:54:28 +0000 Subject: [PATCH 4/9] more linux faff --- src/flamegpu/io/Telemetry.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index a72b8e59b..cbdb19aaf 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -320,8 +320,9 @@ std::string Telemetry::getConfigDirectory() { return std::string(home) + "/.config"; } else { - struct passwd* pwd = getpwuid_r(getuid()); - if (pwd) { + struct passwd* pwd; + int success = getpwuid_r(getuid(), pwd); + if (success) { return std::string(pwd->pw_dir) + "/.config"; } } From 237f09863c2e0bf0ce60477f805e9877b52e1665 Mon Sep 17 00:00:00 2001 From: Mondus Date: Wed, 20 Nov 2024 13:07:25 +0000 Subject: [PATCH 5/9] use of thread safe linux functions fixed --- src/flamegpu/io/Telemetry.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index cbdb19aaf..886cca9d9 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -319,13 +319,15 @@ std::string Telemetry::getConfigDirectory() { if (home) { return std::string(home) + "/.config"; } - else { - struct passwd* pwd; - int success = getpwuid_r(getuid(), pwd); - if (success) { - return std::string(pwd->pw_dir) + "/.config"; - } + // try and get the user directory if home is not set + struct passwd pwd; + struct passwd* result = nullptr; + char buffer[4096]; + int ret = getpwuid_r(getuid(), &pwd, buffer, sizeof(buffer), &result); + if (ret == 0 && result != nullptr) { + return std::string(pwd.pw_dir) + "/.config"; } + throw std::runtime_error("Unable to retrieve config directory on Linux"); #endif } From 3f93cb1e6eb3a844cce1af9c948383bbfc263682 Mon Sep 17 00:00:00 2001 From: Mondus Date: Wed, 20 Nov 2024 14:12:26 +0000 Subject: [PATCH 6/9] fixing review points --- src/flamegpu/io/Telemetry.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index 886cca9d9..e28503b34 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -364,9 +364,14 @@ std::string Telemetry::getUserId() { if (std::filesystem::exists(filePath)) { std::ifstream file(filePath); if (file.is_open()) { - std::getline(file, userId); // overwrite existing Id + std::string cached_id; + std::getline(file, cached_id); // overwrite existing Id file.close(); - return userId; // Config file and user id found so return it + // Config file and user id found so return it if not empty (either because file is externally modified or file is a directory) + if (!cached_id.empty()) + return cached_id; + else + return userId; } else { throw std::runtime_error("Unable to open user ID file for reading"); @@ -382,7 +387,7 @@ std::string Telemetry::getUserId() { throw std::runtime_error("Unable to create user ID file"); } } catch (const std::exception&) { - fprintf(stderr, "Warning: Telemetry User Id file is not read/writeable from config file. A new User Id will be used."); + fprintf(stderr, "Warning: Telemetry User Id file is not read/writeable from config file. A new User Id will be used.\n"); } return userId; } From 7916a9c84685cc8c11fe249df4d509bca694b59b Mon Sep 17 00:00:00 2001 From: Peter Heywood Date: Thu, 21 Nov 2024 13:30:39 +0000 Subject: [PATCH 7/9] Telemetry: Change telemetry config dir to lower case, matching the jitify cache dir --- src/flamegpu/io/Telemetry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index e28503b34..e9135097d 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -356,7 +356,7 @@ std::string Telemetry::getUserId() { // Try to load an existing ID from file if it exists try { // Determine config file location - std::string configDir = Telemetry::getConfigDirectory() + "/FLAMEGPU"; + std::string configDir = Telemetry::getConfigDirectory() + "/flamegpu"; std::filesystem::create_directories(configDir); // Ensure the directory exists std::string filePath = configDir + "/flamegpu_user.cfg"; From bb4c106aec9575667d31425ad3be4bdb2a143f65 Mon Sep 17 00:00:00 2001 From: Peter Heywood Date: Thu, 21 Nov 2024 13:51:34 +0000 Subject: [PATCH 8/9] Telemetry: Change telemtery user file name for clarity --- include/flamegpu/io/Telemetry.h | 2 +- src/flamegpu/io/Telemetry.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/flamegpu/io/Telemetry.h b/include/flamegpu/io/Telemetry.h index a99e39147..efefadf46 100644 --- a/include/flamegpu/io/Telemetry.h +++ b/include/flamegpu/io/Telemetry.h @@ -98,7 +98,7 @@ static std::string getConfigDirectory(); static std::string generateRandomId(); /** - * Obtains a unique user Id. If a configuration file (flamegpu_user.cfg) exists this will be loaded from disk otherwise it will be generated and stored in the configuration location. If the configuration location is not writeable a new user Id will be generated each time. The user Id will be further obfuscated by Telemetry Deck which will salt and hash the Id. + * Obtains a unique user Id. If a configuration file (i.e. ${XDG_CONFIG_HOME}/flamegpu/telemetry_user.cfg on linux) exists this will be loaded from disk otherwise it will be generated and stored in the configuration location. If the configuration location is not writeable a new user Id will be generated each time. The user Id will be further obfuscated by Telemetry Deck which will salt and hash the Id. * @return A 36 character randomised alphanumeric string representing a unique user Id */ static std::string getUserId(); diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index e9135097d..73d48c24a 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -358,7 +358,7 @@ std::string Telemetry::getUserId() { // Determine config file location std::string configDir = Telemetry::getConfigDirectory() + "/flamegpu"; std::filesystem::create_directories(configDir); // Ensure the directory exists - std::string filePath = configDir + "/flamegpu_user.cfg"; + std::string filePath = configDir + "/telemetry_user.cfg"; // Check if the file exists if (std::filesystem::exists(filePath)) { From 4516103d0e1a44b794696635eff9c54713ed91fa Mon Sep 17 00:00:00 2001 From: Peter Heywood Date: Thu, 21 Nov 2024 13:51:56 +0000 Subject: [PATCH 9/9] Telemetry: Open telemetry cfg file in binary mode --- src/flamegpu/io/Telemetry.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flamegpu/io/Telemetry.cpp b/src/flamegpu/io/Telemetry.cpp index 73d48c24a..cc2b292ee 100644 --- a/src/flamegpu/io/Telemetry.cpp +++ b/src/flamegpu/io/Telemetry.cpp @@ -362,7 +362,7 @@ std::string Telemetry::getUserId() { // Check if the file exists if (std::filesystem::exists(filePath)) { - std::ifstream file(filePath); + std::ifstream file(filePath, std::ios_base::binary); if (file.is_open()) { std::string cached_id; std::getline(file, cached_id); // overwrite existing Id @@ -378,7 +378,7 @@ std::string Telemetry::getUserId() { } } - std::ofstream file(filePath); + std::ofstream file(filePath, std::ios_base::binary); if (file.is_open()) { file << userId; file.close();