Compare commits

...

4 Commits
v0.2 ... dev

Author SHA1 Message Date
marcelb
a5efeaf654 Some fix, check operator++ 2025-04-09 22:42:21 +02:00
mbandic
e659a78bd1 Make work with string and number keys, cmake 2025-04-04 10:06:25 +02:00
marcelb
da9a917945 License, Readme, comments 2024-01-08 19:39:22 +01:00
marcelb
ba0aa95117 Fix get_data_and_clear() return variable 2024-01-06 16:21:20 +01:00
10 changed files with 300 additions and 61 deletions

1
.gitignore vendored
View File

@ -0,0 +1 @@
build/

52
.vscode/settings.json vendored
View File

@ -8,6 +8,56 @@
"*.tcc": "cpp", "*.tcc": "cpp",
"deque": "cpp", "deque": "cpp",
"unordered_map": "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"
} }
} }

30
CMakeLists.txt Normal file
View File

@ -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)
#

View File

@ -58,7 +58,7 @@ APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [2023] [Marcel Bandić] Copyright [2023] [Marcel Bandić - marcelb96@yahoo.com]
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -0,0 +1,61 @@
# A library for tracking statistics and metrics
A simple library for measuring incremental parameters in C++ programs based on the key-value principle.
## Features
- Object oriented
- Thread safe
- Easy access to counters using the [] operator
- Simple incrementing of counters using the ++ operator
- Initial setup of the list of counters and values
- List of counter names
- Retrieving the status of all counters
- Reset all counters
- Retrieving the state of all counters and resetting the counters
## Installation
Just download the latest release and unzip it into your project. You can turn it on with:
```
#include "metrics/lib/metrics.hpp"
using namespace marcelb;
```
## Usage
```c++
// init
Metrics<string> stats;
// operator [] and increment ++
stats["access"]++;
// print couter access
cout << stats["access"];
// get counters names
auto listCounterNames = stats.keys();
// get all couters
auto data = stats.get_data();
// reset counters
stats.clear();
// set counters
map<string, uint64_t> MyStats = {{"access", 3},{ "error", 0}};
stats.set(MyStats);
// get and clear all counters
auto dataWithClear = stats.get_data_and_clear();
```
## License
[APACHE 2.0](http://www.apache.org/licenses/LICENSE-2.0/)
## Support & Feedback
For support and any feedback, contact the address: marcelb96@yahoo.com.
## Contributing
Contributions are always welcome!
Feel free to fork and start working with or without a later pull request. Or contact for suggest and request an option.

View File

@ -6,68 +6,69 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <shared_mutex>
#include <atomic>
using namespace std; using namespace std;
namespace marcelb { namespace marcelb {
/** /**
* Klasa za mjerenje proizvoljne statistike * A template class for measuring arbitrary statistics
*/ */
template<typename K>
class Metrics { class Metrics {
mutex io; mutable shared_mutex mtx; // Mutex for concurrent read, exclusive write
map<string, uint> counters; map<K, atomic<uint64_t>> counters; // Supports any K (e.g., string, int)
public: public:
/**
Metrics (); * Constructor, without predefining the name of the counter
Metrics (map<string, uint> _counters); */
Metrics();
/** /**
* Operator[] za pristup svakoj brojaču mjerenja * Constructor, with predefined counters from the passed object
*/ */
uint& operator[](const string& key) { Metrics(map<K, uint64_t> _counters);
return counters[key];
}
/** /**
* Operator++ za inkrementalno povećanje brojača mjerenja * Operator[] to access each measurement counter
*/ */
Metrics& operator++ (int n) { atomic<uint64_t>& operator[](const K& key);
lock_guard<mutex> _io(io);
n++;
return *this;
}
void set(map<string, uint> _counters) {
counters = _counters;
}
/** /**
* Metoda za resetiranje brojača * Operator++ to increment the measurement counter incrementally
*/ */
Metrics& operator++(int n);
/**
* Method to set the counter from the passed object
*/
void set(map<K, uint64_t> _counters);
/**
* A method to reset the counter
*/
void clear(); void clear();
/** /**
* Metoda koja vraća vektor stringova svih naziva brojača * A method that returns a vector of strings of all counter names
*/ */
vector<string> keys(); vector<K> keys() const;
/** /**
* Metoda vraća map<string, uint> svih mjerenja * The method returns a map<K, uint64_t> of all measurements
*/ */
map<string, uint> get_data(); map<K, uint64_t> get_data() const;
/** /**
* Metoda vraća map<string, uint> svih mjerenja i resetira brojače * The method returns a map<K, uint64_t> of all measurements and resets the counters
*/ */
map<string, uint> get_data_and_clear(); map<K, uint64_t> get_data_and_clear();
}; };
} }
#endif #endif

View File

@ -1,35 +1,75 @@
#include "../lib/metrics.hpp" #include "../lib/metrics.hpp"
marcelb::Metrics::Metrics() { namespace marcelb {
}
marcelb::Metrics::Metrics(map<string, uint> _counters) { template<typename K>
Metrics<K>::Metrics() {}
template<typename K>
Metrics<K>::Metrics(map<K, uint64_t> _counters) {
set(_counters); set(_counters);
} }
void marcelb::Metrics::clear() { template<typename K>
lock_guard<mutex> _io(io); void Metrics<K>::clear() {
unique_lock<shared_mutex> lock(mtx);
counters.clear(); counters.clear();
return;
} }
vector<string> marcelb::Metrics::keys() { template<typename K>
vector<string> _keys; vector<K> Metrics<K>::keys() const {
for (auto counter : counters) { shared_lock<shared_mutex> lock(mtx);
vector<K> _keys;
for (auto& counter : counters) {
_keys.push_back(counter.first); _keys.push_back(counter.first);
} }
return _keys; return _keys;
} }
template<typename K>
map<string, uint> marcelb::Metrics::get_data() { map<K, uint64_t> Metrics<K>::get_data() const {
return counters; shared_lock<shared_mutex> lock(mtx);
map<K, uint64_t> data;
for (const auto& counter : counters) {
data[counter.first] = counter.second.load();
}
return data;
} }
template<typename K>
map<string, uint> marcelb::Metrics::get_data_and_clear() { map<K, uint64_t> Metrics<K>::get_data_and_clear() {
auto data = counters; map<K, uint64_t> data = get_data();
clear(); clear();
return counters; return data;
}
template<typename K>
atomic<uint64_t>& Metrics<K>::operator[](const K& key) {
shared_lock<shared_mutex> lock(mtx);
return counters[key];
}
template<typename K>
Metrics<K>& Metrics<K>::operator++(int n) {
shared_lock<shared_mutex> lock(mtx);
// Increment all counters by n as an example
// for (auto& counter : counters) {
// counter.second.fetch_add(n, memory_order_relaxed);
// }
n++;
return *this;
}
template<typename K>
void Metrics<K>::set(map<K, uint64_t> _counters) {
unique_lock<shared_mutex> lock(mtx);
counters.clear();
for (auto& counter : _counters) {
counters[counter.first].store(counter.second);
}
}
template class Metrics<string>;
template class Metrics<uint32_t>;
} }

3
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,3 @@
add_executable(metrics_test test.cpp)
target_link_libraries(metrics_test metrics)

BIN
test/test

Binary file not shown.

View File

@ -1,22 +1,75 @@
#include <iostream>
#include <string>
#include <atomic>
using namespace std;
#include "../lib/metrics.hpp" #include "../lib/metrics.hpp"
using namespace marcelb; using namespace marcelb;
int main() { int main() {
Metrics metrika; // atomic<int> a(0);
// a++;
// cout << a << endl;
Metrics<string> metrika;
cout << " access " << metrika["access"]++ << endl; cout << " access " << metrika["access"]++ << endl;
cout << " access " << metrika["access"]++ << endl; cout << " access " << metrika["access"]++ << endl;
cout << " error " << metrika["error"] << endl; cout << " error " << metrika["error"] << endl;
cout << " access " << metrika["access"] << endl; cout << " access " << metrika["access"] << endl;
metrika.keys(); // metrika.keys();
cout << " error " << metrika["error"] << endl; cout << " error " << metrika["error"] << endl;
cout << " access " << metrika["access"] << endl; cout << " access " << metrika["access"] << endl;
Metrics<uint32_t> 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 ++
// stats["access"]++;
// // print couter access
// cout << stats["access"];
// // get counters names
// auto listCounterNames = stats.keys();
// // get all couters
// auto data = stats.get_data();
// // reset counters
// stats.clear();
// // set counters
// map<string, uint64_t> MyStats = {{"access", 3},{ "error", 0}};
// stats.set(MyStats);
// // get and clear all counters
auto dataWithClear = metrika.get_data_and_clear();
for (auto& [key, value] : dataWithClear) {
cout << "Log analitic " << key << ", value: " << value << endl;
}
return 0; return 0;
} }