From e659a78bd1f766ecdf63bd65d2b5073ed9183ae6 Mon Sep 17 00:00:00 2001 From: mbandic Date: Fri, 4 Apr 2025 10:06:25 +0200 Subject: [PATCH] Make work with string and number keys, cmake --- .gitignore | 1 + .vscode/settings.json | 52 ++++++++++++++++++++++++++++- CMakeLists.txt | 30 +++++++++++++++++ README.md | 4 +-- lib/metrics.hpp | 64 ++++++++++++++++------------------- src/metrics.cpp | 75 +++++++++++++++++++++++++++++++++--------- test/CMakeLists.txt | 3 ++ test/test | Bin 92120 -> 0 bytes test/test.cpp | 39 ++++++++++++++++++++-- 9 files changed, 210 insertions(+), 58 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 test/CMakeLists.txt delete mode 100755 test/test diff --git a/.gitignore b/.gitignore index e69de29..d163863 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 4531e4f..a6228a6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,56 @@ "*.tcc": "cpp", "deque": "cpp", "unordered_map": "cpp", - "system_error": "cpp" + "system_error": "cpp", + "atomic": "cpp", + "shared_mutex": "cpp", + "mutex": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "array": "cpp", + "bit": "cpp", + "chrono": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "semaphore": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "variant": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..cd21d5c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.10) + +project(metrics) + +# Postavi verziju projekta +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Pronađi Boost biblioteku (ako nije uobičajeni direktorijum, postavi put) +# find_package(Boost REQUIRED COMPONENTS system) + +# Dodaj direktorijume sa zaglavljima +include_directories(lib) + +# Dodaj biblioteku +add_library(metrics STATIC + src/metrics.cpp +) + +# # Linkaj log biblioteku sa Boost-om +# target_link_libraries(log Boost::system) + +# Dodaj testove +add_subdirectory(test) + + +# Instaliraj biblioteku +# install(TARGETS log DESTINATION lib) +# install(FILES lib/log.hpp lib/define.hpp lib/engine.hpp lib/filesystem.hpp lib/timers.hpp lib/trigger.hpp DESTINATION include/log) +# \ No newline at end of file diff --git a/README.md b/README.md index dcf224d..c0b97e9 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ using namespace marcelb; ```c++ // init -Metrics stats; +Metrics stats; // operator [] and increment ++ stats["access"]++; // print couter access @@ -39,7 +39,7 @@ auto data = stats.get_data(); // reset counters stats.clear(); // set counters -map MyStats = {{"access", 3},{ "error", 0}}; +map MyStats = {{"access", 3},{ "error", 0}}; stats.set(MyStats); // get and clear all counters auto dataWithClear = stats.get_data_and_clear(); diff --git a/lib/metrics.hpp b/lib/metrics.hpp index f75130c..c9fe533 100644 --- a/lib/metrics.hpp +++ b/lib/metrics.hpp @@ -6,77 +6,69 @@ #include #include #include +#include +#include using namespace std; namespace marcelb { /** - * A class for measuring arbitrary statistics -*/ + * A template class for measuring arbitrary statistics + */ +template class Metrics { - mutex io; - map counters; - - public: + mutable shared_mutex mtx; // Mutex for concurrent read, exclusive write + map> counters; // Supports any K (e.g., string, int) +public: /** * Constructor, without predefining the name of the counter - */ - Metrics (); + */ + Metrics(); /** * Constructor, with predefined counters from the passed object - */ - Metrics (map _counters); + */ + Metrics(map _counters); /** * Operator[] to access each measurement counter - */ - uint& operator[](const string& key) { - return counters[key]; - } + */ + atomic& operator[](const K& key); /** * Operator++ to increment the measurement counter incrementally - */ - Metrics& operator++ (int n) { - lock_guard _io(io); - n++; - return *this; - } + */ + Metrics& operator++(int n); /** * Method to set the counter from the passed object - */ - void set(map _counters) { - counters = _counters; - } + */ + void set(map _counters); /** * A method to reset the counter - */ + */ void clear(); /** - * A method that returns a vector os strings of all counter names - */ - vector keys(); + * A method that returns a vector of strings of all counter names + */ + vector keys() const; /** - * The method returns a map of all measurements - */ - map get_data(); + * The method returns a map of all measurements + */ + map get_data() const; /** - * The method returns a map of all measurements and resets the counters - */ - map get_data_and_clear(); - + * The method returns a map of all measurements and resets the counters + */ + map get_data_and_clear(); }; - } #endif \ No newline at end of file diff --git a/src/metrics.cpp b/src/metrics.cpp index b48d149..9a30874 100644 --- a/src/metrics.cpp +++ b/src/metrics.cpp @@ -1,35 +1,78 @@ #include "../lib/metrics.hpp" -marcelb::Metrics::Metrics() { -} +namespace marcelb { -marcelb::Metrics::Metrics(map _counters) { +template +Metrics::Metrics() {} + +template +Metrics::Metrics(map _counters) { set(_counters); } -void marcelb::Metrics::clear() { - lock_guard _io(io); +template +void Metrics::clear() { + unique_lock lock(mtx); counters.clear(); - return; } -vector marcelb::Metrics::keys() { - vector _keys; - for (auto counter : counters) { +template +vector Metrics::keys() const { + shared_lock lock(mtx); + vector _keys; + for (auto& counter : counters) { _keys.push_back(counter.first); } - return _keys; } - -map marcelb::Metrics::get_data() { - return counters; +template +map Metrics::get_data() const { + shared_lock lock(mtx); + map data; + for (const auto& counter : counters) { + data[counter.first] = counter.second.load(); + } + return data; } - -map marcelb::Metrics::get_data_and_clear() { - auto data = counters; +template +map Metrics::get_data_and_clear() { + map data; + { + shared_lock lock(mtx); + auto data = get_data(); + } clear(); return data; +} + +template +atomic& Metrics::operator[](const K& key) { + shared_lock lock(mtx); + return counters[key]; +} + +template +Metrics& Metrics::operator++(int n) { + shared_lock lock(mtx); + // Increment all counters by n as an example + for (auto& counter : counters) { + counter.second.fetch_add(n, memory_order_relaxed); + } + return *this; +} + +template +void Metrics::set(map _counters) { + unique_lock lock(mtx); + counters.clear(); + for (auto& counter : _counters) { + counters[counter.first].store(counter.second); + } +} + +template class Metrics; +template class Metrics; + } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..a8e77d2 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(metrics_test test.cpp) + +target_link_libraries(metrics_test metrics) \ No newline at end of file diff --git a/test/test b/test/test deleted file mode 100755 index db2161a63f4f277b80ee82d5ea40a54b801aa688..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92120 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 +#include +#include + +using namespace std; + #include "../lib/metrics.hpp" using namespace marcelb; int main() { - Metrics metrika; + // atomic a(0); + + // a++; + + // cout << a << endl; + + Metrics metrika; cout << " access " << metrika["access"]++ << endl; cout << " access " << metrika["access"]++ << endl; cout << " error " << metrika["error"] << endl; cout << " access " << metrika["access"] << endl; - metrika.keys(); + // metrika.keys(); cout << " error " << metrika["error"] << endl; cout << " access " << metrika["access"] << endl; + Metrics metrika2; + + + enum keys { + access = 1, + error + }; + + + + cout << " access " << metrika2[keys::access]++ << endl; + cout << " access " << metrika2[keys::access]++ << endl; + cout << " error " << metrika2[keys::error] << endl; + cout << " access " << metrika2[keys::access] << endl; + + // metrika2.keys(); + + cout << " error " << metrika2[keys::error] << endl; + cout << " access " << metrika2[keys::access] << endl; + + // // init // Metrics stats; // // operator [] and increment ++ @@ -29,7 +62,7 @@ int main() { // // reset counters // stats.clear(); // // set counters - // map MyStats = {{"access", 3},{ "error", 0}}; + // map MyStats = {{"access", 3},{ "error", 0}}; // stats.set(MyStats); // // get and clear all counters // auto dataWithClear = stats.get_data_and_clear();