Loading CHANGELOG.md +1 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### New - Added Stats ([!128](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/128)) gathering in servers - Added Stats ([!132](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/132)) gathering in servers - GKFS_CHUNK_STATS enables chunk usage output - Stats output can be enabled with --output-stats <filename> - Added new experimental metadata backend: Loading README.md +2 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,8 @@ Once it is enabled, `--dbbackend` option will be functional. ### Stats Pushing stats to Prometheus is enabled with the `-DGKFS_ENABLE_PROMETHEUS` and the setup of the `--output-stats <FILE>`. Without the last one, the push to the gateway is disabled. Stats for each chunk (read-write access) can be enabled with `-DGKFS_CHUNK_STATS`. The server will store file/chunk number stats. ### Acknowledgment Loading hermes @ 38d82118 Compare 0af45bfa to 38d82118 Original line number Diff line number Diff line Subproject commit 0af45bfa667f7ff9c78167ef94d975bffbd879f0 Subproject commit 38d821182ef2b6c6961595bf011ca69bf78bc936 spdlog @ eb322062 Original line number Diff line number Diff line Subproject commit eb3220622e73a4889eee355ffa37972b3cac3df5 include/common/statistics/stats.hpp +82 −79 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <iostream> #include <iomanip> #include <fstream> #include <config.hpp> // PROMETHEUS includes Loading @@ -64,77 +65,71 @@ using namespace prometheus; */ namespace gkfs::utils { /* Number of operations (Create, write/ read, remove, mkdir...) Size of database (metadata keys, should be not needed, any) Size of data (+write - delete) Server Bandwidth (write / read operations) mean, (lifetime of the server) 1 minute mean 5 minute mean 10 minute mean To provide the stats that we need, we need to store the info and the timestamp to calculate it A vector should work, with a maximum of elements, The stats will only be calculated when requested a cached value will be send (with a deadline) /** * * Number of operations (Create, write/ read, remove, mkdir...) * Size of database (metadata keys, should be not needed, any) * Size of data (+write - delete) * Server Bandwidth (write / read operations) * * mean, (lifetime of the server) * 1 minute mean * 5 minute mean * 10 minute mean * * To provide the stats that we need, * we need to store the info and the timestamp to calculate it * A vector should work, with a maximum of elements, */ class Stats { public: enum class IOPS_OP { IOPS_CREATE, IOPS_WRITE, IOPS_READ, IOPS_STATS, IOPS_DIRENTS, IOPS_REMOVE, enum class IopsOp { iops_create, iops_write, iops_read, iops_stats, iops_dirent, iops_remove, }; ///< enum storing IOPS Stats enum class SIZE_OP { WRITE_SIZE, READ_SIZE }; ///< enum storing Size Stats enum class SizeOp { write_size, read_size }; ///< enum storing Size Stats private: constexpr static const std::initializer_list<Stats::IOPS_OP> all_IOPS_OP = { IOPS_OP::IOPS_CREATE, IOPS_OP::IOPS_WRITE, IOPS_OP::IOPS_READ, IOPS_OP::IOPS_STATS, IOPS_OP::IOPS_DIRENTS, IOPS_OP::IOPS_REMOVE}; ///< Enum IOPS iterator constexpr static const std::initializer_list<Stats::SIZE_OP> all_SIZE_OP = { SIZE_OP::WRITE_SIZE, SIZE_OP::READ_SIZE}; ///< Enum SIZE iterator const std::vector<std::string> IOPS_OP_S = { constexpr static const std::initializer_list<Stats::IopsOp> all_IopsOp = { IopsOp::iops_create, IopsOp::iops_write, IopsOp::iops_read, IopsOp::iops_stats, IopsOp::iops_dirent, IopsOp::iops_remove}; ///< Enum IOPS iterator constexpr static const std::initializer_list<Stats::SizeOp> all_SizeOp = { SizeOp::write_size, SizeOp::read_size}; ///< Enum SIZE iterator const std::vector<std::string> IopsOp_s = { "IOPS_CREATE", "IOPS_WRITE", "IOPS_READ", "IOPS_STATS", "IOPS_DIRENTS", "IOPS_REMOVE"}; ///< Stats Labels const std::vector<std::string> SIZE_OP_S = {"WRITE_SIZE", const std::vector<std::string> SizeOp_s = {"WRITE_SIZE", "READ_SIZE"}; ///< Stats Labels std::chrono::time_point<std::chrono::steady_clock> start; ///< When we started the server const unsigned int MAX_STATS = 1000000; ///< How many stats will be stored std::map<IOPS_OP, unsigned long> std::map<IopsOp, unsigned long> IOPS; ///< Stores total value for global mean std::map<SIZE_OP, unsigned long> std::map<SizeOp, unsigned long> SIZE; ///< Stores total value for global mean std::map<IOPS_OP, std::map<IopsOp, std::deque<std::chrono::time_point<std::chrono::steady_clock>>> TIME_IOPS; ///< Stores timestamp when an operation comes removes if TimeIops; ///< Stores timestamp when an operation comes removes if ///< first operation if > 10 minutes Different means will ///< be stored and cached 1 minuted std::map<enum SIZE_OP, std::deque<std::pair< std::map<SizeOp, std::deque<std::pair< std::chrono::time_point<std::chrono::steady_clock>, unsigned long long>>> TIME_SIZE; ///< For size operations we need to store the timestamp TimeSize; ///< For size operations we need to store the timestamp ///< and the size Loading @@ -154,9 +149,9 @@ private: output(std::chrono::seconds d, std::string file_output); std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_READ; ///< Stores the number of times a chunk/file is read chunkRead; ///< Stores the number of times a chunk/file is read std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_WRITE; ///< Stores the number of times a chunk/file is write chunkWrite; ///< Stores the number of times a chunk/file is write /** * @brief Called by output to generate CHUNK map Loading @@ -179,10 +174,12 @@ private: #ifdef GKFS_ENABLE_PROMETHEUS std::shared_ptr<Gateway> gateway; ///< Prometheus Gateway std::shared_ptr<Registry> registry; ///< Prometheus Counters Registry Family<Counter>* family_counter; ///< Prometheus IOPS counter Family<Summary>* family_summary; ///< Prometheus SIZE counter std::map<IOPS_OP, Counter*> IOPS_Prometheus; std::map<SIZE_OP, Summary*> SIZE_Prometheus; Family<Counter>* family_counter; ///< Prometheus IOPS counter (managed by ///< Prometheus cpp) Family<Summary>* family_summary; ///< Prometheus SIZE counter (managed by ///< Prometheus cpp) std::map<IopsOp, Counter*> iops_Prometheus; ///< Prometheus IOPS metrics std::map<SizeOp, Summary*> size_Prometheus; ///< Prometheus SIZE metrics #endif public: Loading @@ -190,9 +187,10 @@ public: * @brief Starts the Stats module and initializes structures * @param output_thread creates an aditional thread that outputs the stats * @param filename file where to write the output * @param prometheus_gateway ip:port to expose the metrics */ Stats(bool output_thread, std::string filename, std::string prometheus_gateway); Stats(bool output_thread, const std::string& filename, const std::string& prometheus_gateway); /** * @brief Destroys the class, and any associated thread Loading @@ -204,28 +202,29 @@ public: /** * @brief Set the up Prometheus gateway and structures * * @param gateway_ip * @param gateway_port * @param gateway_ip ip of the prometheus gateway * @param gateway_port port of the prometheus gateway */ void setup_Prometheus(std::string gateway_ip, std::string gateway_port); setup_Prometheus(const std::string& gateway_ip, const std::string& gateway_port); /** * @brief Adds a new read access to the chunk/path specified * * @param path * @param chunk * @param path path of the chunk * @param chunk chunk number */ void add_read(std::string path, unsigned long long chunk); add_read(const std::string& path, unsigned long long chunk); /** * @brief Adds a new write access to the chunk/path specified * * @param path * @param chunk * @param path path of the chunk * @param chunk chunk number */ void add_write(std::string path, unsigned long long chunk); add_write(const std::string& path, unsigned long long chunk); /** Loading @@ -233,52 +232,56 @@ public: * No value needed as they are simple (1 create, 1 read...) * Size operations internally call this operation (read,write) * * @param IOPS_OP Which operation to add * @param IopsOp Which operation to add */ void add_value_iops(enum IOPS_OP); void add_value_iops(enum IopsOp); /** * @brief Store a new stat point, with a size value. * If it involves a IO operations it will call the corresponding * operation * * @param SIZE_OP Which operation we refer * @param value to store (SIZE_OP) * @param SizeOp Which operation we refer * @param value to store (SizeOp) */ void add_value_size(enum SIZE_OP, unsigned long long value); add_value_size(enum SizeOp, unsigned long long value); /** * @brief Get the total mean value of the asked stat * This can be provided inmediately without cost * @param IopsOp Which operation to get * @return mean value */ double get_mean(enum IOPS_OP); double get_mean(enum IopsOp); /** * @brief Get the total mean value of the asked stat * This can be provided inmediately without cost * @param SizeOp Which operation to get * @return mean value */ double get_mean(enum SIZE_OP); double get_mean(enum SizeOp); /** * @brief Get all the means (total, 1,5 and 10 minutes) for a SIZE_OP * Returns precalculated values if we just calculated them 1 minute ago * @param SizeOp Which operation to get * * @return std::vector< double > with 4 means */ std::vector<double> get_four_means(enum SIZE_OP); std::vector<double> get_four_means(enum SizeOp); /** * @brief Get all the means (total, 1,5 and 10 minutes) for a IOPS_OP * Returns precalculated values if we just calculated them 1 minute ago * @param IopsOp Which operation to get * * @return std::vector< double > with 4 means */ std::vector<double> get_four_means(enum IOPS_OP); std::vector<double> get_four_means(enum IopsOp); }; } // namespace gkfs::utils Loading Loading
CHANGELOG.md +1 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### New - Added Stats ([!128](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/128)) gathering in servers - Added Stats ([!132](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/132)) gathering in servers - GKFS_CHUNK_STATS enables chunk usage output - Stats output can be enabled with --output-stats <filename> - Added new experimental metadata backend: Loading
README.md +2 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,8 @@ Once it is enabled, `--dbbackend` option will be functional. ### Stats Pushing stats to Prometheus is enabled with the `-DGKFS_ENABLE_PROMETHEUS` and the setup of the `--output-stats <FILE>`. Without the last one, the push to the gateway is disabled. Stats for each chunk (read-write access) can be enabled with `-DGKFS_CHUNK_STATS`. The server will store file/chunk number stats. ### Acknowledgment Loading
hermes @ 38d82118 Compare 0af45bfa to 38d82118 Original line number Diff line number Diff line Subproject commit 0af45bfa667f7ff9c78167ef94d975bffbd879f0 Subproject commit 38d821182ef2b6c6961595bf011ca69bf78bc936
spdlog @ eb322062 Original line number Diff line number Diff line Subproject commit eb3220622e73a4889eee355ffa37972b3cac3df5
include/common/statistics/stats.hpp +82 −79 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <iostream> #include <iomanip> #include <fstream> #include <config.hpp> // PROMETHEUS includes Loading @@ -64,77 +65,71 @@ using namespace prometheus; */ namespace gkfs::utils { /* Number of operations (Create, write/ read, remove, mkdir...) Size of database (metadata keys, should be not needed, any) Size of data (+write - delete) Server Bandwidth (write / read operations) mean, (lifetime of the server) 1 minute mean 5 minute mean 10 minute mean To provide the stats that we need, we need to store the info and the timestamp to calculate it A vector should work, with a maximum of elements, The stats will only be calculated when requested a cached value will be send (with a deadline) /** * * Number of operations (Create, write/ read, remove, mkdir...) * Size of database (metadata keys, should be not needed, any) * Size of data (+write - delete) * Server Bandwidth (write / read operations) * * mean, (lifetime of the server) * 1 minute mean * 5 minute mean * 10 minute mean * * To provide the stats that we need, * we need to store the info and the timestamp to calculate it * A vector should work, with a maximum of elements, */ class Stats { public: enum class IOPS_OP { IOPS_CREATE, IOPS_WRITE, IOPS_READ, IOPS_STATS, IOPS_DIRENTS, IOPS_REMOVE, enum class IopsOp { iops_create, iops_write, iops_read, iops_stats, iops_dirent, iops_remove, }; ///< enum storing IOPS Stats enum class SIZE_OP { WRITE_SIZE, READ_SIZE }; ///< enum storing Size Stats enum class SizeOp { write_size, read_size }; ///< enum storing Size Stats private: constexpr static const std::initializer_list<Stats::IOPS_OP> all_IOPS_OP = { IOPS_OP::IOPS_CREATE, IOPS_OP::IOPS_WRITE, IOPS_OP::IOPS_READ, IOPS_OP::IOPS_STATS, IOPS_OP::IOPS_DIRENTS, IOPS_OP::IOPS_REMOVE}; ///< Enum IOPS iterator constexpr static const std::initializer_list<Stats::SIZE_OP> all_SIZE_OP = { SIZE_OP::WRITE_SIZE, SIZE_OP::READ_SIZE}; ///< Enum SIZE iterator const std::vector<std::string> IOPS_OP_S = { constexpr static const std::initializer_list<Stats::IopsOp> all_IopsOp = { IopsOp::iops_create, IopsOp::iops_write, IopsOp::iops_read, IopsOp::iops_stats, IopsOp::iops_dirent, IopsOp::iops_remove}; ///< Enum IOPS iterator constexpr static const std::initializer_list<Stats::SizeOp> all_SizeOp = { SizeOp::write_size, SizeOp::read_size}; ///< Enum SIZE iterator const std::vector<std::string> IopsOp_s = { "IOPS_CREATE", "IOPS_WRITE", "IOPS_READ", "IOPS_STATS", "IOPS_DIRENTS", "IOPS_REMOVE"}; ///< Stats Labels const std::vector<std::string> SIZE_OP_S = {"WRITE_SIZE", const std::vector<std::string> SizeOp_s = {"WRITE_SIZE", "READ_SIZE"}; ///< Stats Labels std::chrono::time_point<std::chrono::steady_clock> start; ///< When we started the server const unsigned int MAX_STATS = 1000000; ///< How many stats will be stored std::map<IOPS_OP, unsigned long> std::map<IopsOp, unsigned long> IOPS; ///< Stores total value for global mean std::map<SIZE_OP, unsigned long> std::map<SizeOp, unsigned long> SIZE; ///< Stores total value for global mean std::map<IOPS_OP, std::map<IopsOp, std::deque<std::chrono::time_point<std::chrono::steady_clock>>> TIME_IOPS; ///< Stores timestamp when an operation comes removes if TimeIops; ///< Stores timestamp when an operation comes removes if ///< first operation if > 10 minutes Different means will ///< be stored and cached 1 minuted std::map<enum SIZE_OP, std::deque<std::pair< std::map<SizeOp, std::deque<std::pair< std::chrono::time_point<std::chrono::steady_clock>, unsigned long long>>> TIME_SIZE; ///< For size operations we need to store the timestamp TimeSize; ///< For size operations we need to store the timestamp ///< and the size Loading @@ -154,9 +149,9 @@ private: output(std::chrono::seconds d, std::string file_output); std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_READ; ///< Stores the number of times a chunk/file is read chunkRead; ///< Stores the number of times a chunk/file is read std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_WRITE; ///< Stores the number of times a chunk/file is write chunkWrite; ///< Stores the number of times a chunk/file is write /** * @brief Called by output to generate CHUNK map Loading @@ -179,10 +174,12 @@ private: #ifdef GKFS_ENABLE_PROMETHEUS std::shared_ptr<Gateway> gateway; ///< Prometheus Gateway std::shared_ptr<Registry> registry; ///< Prometheus Counters Registry Family<Counter>* family_counter; ///< Prometheus IOPS counter Family<Summary>* family_summary; ///< Prometheus SIZE counter std::map<IOPS_OP, Counter*> IOPS_Prometheus; std::map<SIZE_OP, Summary*> SIZE_Prometheus; Family<Counter>* family_counter; ///< Prometheus IOPS counter (managed by ///< Prometheus cpp) Family<Summary>* family_summary; ///< Prometheus SIZE counter (managed by ///< Prometheus cpp) std::map<IopsOp, Counter*> iops_Prometheus; ///< Prometheus IOPS metrics std::map<SizeOp, Summary*> size_Prometheus; ///< Prometheus SIZE metrics #endif public: Loading @@ -190,9 +187,10 @@ public: * @brief Starts the Stats module and initializes structures * @param output_thread creates an aditional thread that outputs the stats * @param filename file where to write the output * @param prometheus_gateway ip:port to expose the metrics */ Stats(bool output_thread, std::string filename, std::string prometheus_gateway); Stats(bool output_thread, const std::string& filename, const std::string& prometheus_gateway); /** * @brief Destroys the class, and any associated thread Loading @@ -204,28 +202,29 @@ public: /** * @brief Set the up Prometheus gateway and structures * * @param gateway_ip * @param gateway_port * @param gateway_ip ip of the prometheus gateway * @param gateway_port port of the prometheus gateway */ void setup_Prometheus(std::string gateway_ip, std::string gateway_port); setup_Prometheus(const std::string& gateway_ip, const std::string& gateway_port); /** * @brief Adds a new read access to the chunk/path specified * * @param path * @param chunk * @param path path of the chunk * @param chunk chunk number */ void add_read(std::string path, unsigned long long chunk); add_read(const std::string& path, unsigned long long chunk); /** * @brief Adds a new write access to the chunk/path specified * * @param path * @param chunk * @param path path of the chunk * @param chunk chunk number */ void add_write(std::string path, unsigned long long chunk); add_write(const std::string& path, unsigned long long chunk); /** Loading @@ -233,52 +232,56 @@ public: * No value needed as they are simple (1 create, 1 read...) * Size operations internally call this operation (read,write) * * @param IOPS_OP Which operation to add * @param IopsOp Which operation to add */ void add_value_iops(enum IOPS_OP); void add_value_iops(enum IopsOp); /** * @brief Store a new stat point, with a size value. * If it involves a IO operations it will call the corresponding * operation * * @param SIZE_OP Which operation we refer * @param value to store (SIZE_OP) * @param SizeOp Which operation we refer * @param value to store (SizeOp) */ void add_value_size(enum SIZE_OP, unsigned long long value); add_value_size(enum SizeOp, unsigned long long value); /** * @brief Get the total mean value of the asked stat * This can be provided inmediately without cost * @param IopsOp Which operation to get * @return mean value */ double get_mean(enum IOPS_OP); double get_mean(enum IopsOp); /** * @brief Get the total mean value of the asked stat * This can be provided inmediately without cost * @param SizeOp Which operation to get * @return mean value */ double get_mean(enum SIZE_OP); double get_mean(enum SizeOp); /** * @brief Get all the means (total, 1,5 and 10 minutes) for a SIZE_OP * Returns precalculated values if we just calculated them 1 minute ago * @param SizeOp Which operation to get * * @return std::vector< double > with 4 means */ std::vector<double> get_four_means(enum SIZE_OP); std::vector<double> get_four_means(enum SizeOp); /** * @brief Get all the means (total, 1,5 and 10 minutes) for a IOPS_OP * Returns precalculated values if we just calculated them 1 minute ago * @param IopsOp Which operation to get * * @return std::vector< double > with 4 means */ std::vector<double> get_four_means(enum IOPS_OP); std::vector<double> get_four_means(enum IopsOp); }; } // namespace gkfs::utils Loading