Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[new feature]Add metrics #674

Merged
merged 21 commits into from
Jun 7, 2024
66 changes: 33 additions & 33 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,41 @@ on:
workflow_dispatch:

jobs:
windows_msvc:
runs-on: windows-latest
# windows_msvc:
# runs-on: windows-latest

strategy:
matrix:
mode: [ Release ] #[ Release, Debug ] #Debug not support ccache
#https://github.com/ccache/ccache/wiki/MS-Visual-Studio
#https://github.com/ccache/ccache/issues/1040
arch: [ amd64, x86 ] #[ amd64,x86 ]
ssl: [ OFF ] #[ ON, OFF ]
# strategy:
# matrix:
# mode: [ Release ] #[ Release, Debug ] #Debug not support ccache
# #https://github.com/ccache/ccache/wiki/MS-Visual-Studio
# #https://github.com/ccache/ccache/issues/1040
# arch: [ amd64, x86 ] #[ amd64,x86 ]
# ssl: [ OFF ] #[ ON, OFF ]

steps:
- name: Checkout
uses: actions/checkout@v3
- name: Enable Developer Command Prompt
uses: ilammy/[email protected]
with:
arch: ${{ matrix.arch }}
- name: Install ninja-build tool
uses: seanmiddleditch/gha-setup-ninja@master
with:
version: 1.11.1
- name: latest ccache
run: choco install ccache
- name: ccache
uses: hendrikmuhs/[email protected]
with:
key: ${{ github.job }}-${{ matrix.mode}}-ssl( ${{ matrix.ssl}} )-arch-${{ matrix.arch}}
- name: Configure CMake
run: cmake -B ${{github.workspace}}\build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DYLT_ENABLE_SSL=${{matrix.ssl}} -DUSE_CCACHE=ON
- name: Build
run: cmake --build ${{github.workspace}}\build
- name: Test
working-directory: ${{github.workspace}}\build
run: ctest -C ${{matrix.mode}} -j 1 -V
# steps:
# - name: Checkout
# uses: actions/checkout@v3
# - name: Enable Developer Command Prompt
# uses: ilammy/[email protected]
# with:
# arch: ${{ matrix.arch }}
# - name: Install ninja-build tool
# uses: seanmiddleditch/gha-setup-ninja@master
# with:
# version: 1.11.1
# - name: latest ccache
# run: choco install ccache
# - name: ccache
# uses: hendrikmuhs/[email protected]
# with:
# key: ${{ github.job }}-${{ matrix.mode}}-ssl( ${{ matrix.ssl}} )-arch-${{ matrix.arch}}
# - name: Configure CMake
# run: cmake -B ${{github.workspace}}\build -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.mode }} -DYLT_ENABLE_SSL=${{matrix.ssl}} -DUSE_CCACHE=ON
# - name: Build
# run: cmake --build ${{github.workspace}}\build
# - name: Test
# working-directory: ${{github.workspace}}\build
# run: ctest -C ${{matrix.mode}} -j 1 -V
windows_msvc_2019:
runs-on: windows-2019

Expand Down
1 change: 0 additions & 1 deletion include/ylt/coro_http/coro_http_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/
#pragma once
#include "cinatra/uri.hpp"
#ifdef YLT_ENABLE_SSL
#define CINATRA_ENABLE_SSL
#endif
Expand Down
17 changes: 15 additions & 2 deletions include/ylt/coro_io/io_context_pool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asio/steady_timer.hpp>
#include <atomic>
#include <future>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
Expand Down Expand Up @@ -117,6 +118,8 @@ class io_context_pool {
pool_size = 1; // set default value as 1
}

total_thread_num_ += pool_size;

for (std::size_t i = 0; i < pool_size; ++i) {
io_context_ptr io_context(new asio::io_context(1));
work_ptr work(new asio::io_context::work(*io_context));
Expand Down Expand Up @@ -150,8 +153,11 @@ class io_context_pool {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(i, &cpuset);
pthread_setaffinity_np(threads.back()->native_handle(),
sizeof(cpu_set_t), &cpuset);
int rc = pthread_setaffinity_np(threads.back()->native_handle(),
sizeof(cpu_set_t), &cpuset);
if (rc != 0) {
std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
}
}
#endif
}
Expand Down Expand Up @@ -201,6 +207,8 @@ class io_context_pool {
template <typename T>
friend io_context_pool &g_io_context_pool();

static size_t get_total_thread_num() { return total_thread_num_; }

private:
using io_context_ptr = std::shared_ptr<asio::io_context>;
using work_ptr = std::shared_ptr<asio::io_context::work>;
Expand All @@ -213,8 +221,13 @@ class io_context_pool {
std::atomic<bool> has_run_or_stop_ = false;
std::once_flag flag_;
bool cpu_affinity_ = false;
inline static std::atomic<size_t> total_thread_num_ = 0;
};

inline size_t get_total_thread_num() {
return io_context_pool::get_total_thread_num();
}

class multithread_context_pool {
public:
multithread_context_pool(size_t thd_num = std::thread::hardware_concurrency())
Expand Down
258 changes: 258 additions & 0 deletions include/ylt/metric/counter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
#pragma once
#include <atomic>
#include <chrono>

#include "metric.hpp"

namespace ylt {
enum class op_type_t { INC, DEC, SET };
struct counter_sample {
op_type_t op_type;
std::vector<std::string> labels_value;
double value;
};

class counter_t : public metric_t {
public:
// default, no labels, only contains an atomic value.
counter_t(std::string name, std::string help)
: metric_t(MetricType::Counter, std::move(name), std::move(help)) {
use_atomic_ = true;
}

// static labels value, contains a map with atomic value.
counter_t(std::string name, std::string help,
std::map<std::string, std::string> labels)
: metric_t(MetricType::Counter, std::move(name), std::move(help)) {
for (auto &[k, v] : labels) {
labels_name_.push_back(k);
labels_value_.push_back(v);
}

atomic_value_map_.emplace(labels_value_, 0);
use_atomic_ = true;
}

// dynamic labels value
counter_t(std::string name, std::string help,
std::vector<std::string> labels_name)
: metric_t(MetricType::Counter, std::move(name), std::move(help),
std::move(labels_name)) {}

virtual ~counter_t() {}

double value() { return default_lable_value_; }

double value(const std::vector<std::string> &labels_value) {
if (use_atomic_) {
double val = atomic_value_map_[labels_value];
return val;
}
else {
std::lock_guard lock(mtx_);
return value_map_[labels_value];
}
}

std::map<std::vector<std::string>, double,
std::less<std::vector<std::string>>>
value_map() {
std::map<std::vector<std::string>, double,
std::less<std::vector<std::string>>>
map;
if (use_atomic_) {
map = {atomic_value_map_.begin(), atomic_value_map_.end()};
}
else {
std::lock_guard lock(mtx_);
map = value_map_;
}
return map;
}

void serialize(std::string &str) override {
if (labels_name_.empty()) {
if (default_lable_value_ == 0) {
return;
}
serialize_head(str);
serialize_default_label(str);
return;
}

serialize_head(str);
std::string s;
if (use_atomic_) {
serialize_map(atomic_value_map_, s);
}
else {
serialize_map(value_map_, s);
}

if (s.empty()) {
str.clear();
}
else {
str.append(s);
}
}

void inc(double val = 1) {
if (val < 0) {
throw std::invalid_argument("the value is less than zero");
}

#ifdef __APPLE__
mac_os_atomic_fetch_add(&default_lable_value_, val);
#else
default_lable_value_ += val;
#endif
}

void inc(const std::vector<std::string> &labels_value, double value = 1) {
if (value == 0) {
return;
}

validate(labels_value, value);
if (use_atomic_) {
if (labels_value != labels_value_) {
throw std::invalid_argument(
"the given labels_value is not match with origin labels_value");
}
set_value<true>(atomic_value_map_[labels_value], value, op_type_t::INC);
}
else {
std::lock_guard lock(mtx_);
set_value<false>(value_map_[labels_value], value, op_type_t::INC);
}
}

void update(double value) { default_lable_value_ = value; }

void update(const std::vector<std::string> &labels_value, double value) {
if (labels_value.empty() || labels_name_.size() != labels_value.size()) {
throw std::invalid_argument(
"the number of labels_value name and labels_value is not match");
}
if (use_atomic_) {
if (labels_value != labels_value_) {
throw std::invalid_argument(
"the given labels_value is not match with origin labels_value");
}
set_value<true>(atomic_value_map_[labels_value], value, op_type_t::SET);
}
else {
std::lock_guard lock(mtx_);
set_value<false>(value_map_[labels_value], value, op_type_t::SET);
}
}

std::map<std::vector<std::string>, std::atomic<double>,
std::less<std::vector<std::string>>>
&atomic_value_map() {
return atomic_value_map_;
}

protected:
void serialize_default_label(std::string &str) {
str.append(name_);
if (labels_name_.empty()) {
str.append(" ");
}

if (type_ == MetricType::Counter) {
str.append(std::to_string((int64_t)default_lable_value_));
}
else {
str.append(std::to_string(default_lable_value_));
}

str.append("\n");
}

template <typename T>
void serialize_map(T &value_map, std::string &str) {
for (auto &[labels_value, value] : value_map) {
if (value == 0) {
continue;
}
str.append(name_);
str.append("{");
build_string(str, labels_name_, labels_value);
str.append("} ");

if (type_ == MetricType::Counter) {
str.append(std::to_string((int64_t)value));
}
else {
str.append(std::to_string(value));
}

str.append("\n");
}
}

void build_string(std::string &str, const std::vector<std::string> &v1,
const std::vector<std::string> &v2) {
for (size_t i = 0; i < v1.size(); i++) {
str.append(v1[i]).append("=\"").append(v2[i]).append("\"").append(",");
}
str.pop_back();
}

void validate(const std::vector<std::string> &labels_value, double value) {
if (value < 0) {
throw std::invalid_argument("the value is less than zero");
}
if (labels_value.empty() || labels_name_.size() != labels_value.size()) {
throw std::invalid_argument(
"the number of labels_value name and labels_value is not match");
}
}

template <bool is_atomic = false, typename T>
void set_value(T &label_val, double value, op_type_t type) {
switch (type) {
case op_type_t::INC: {
#ifdef __APPLE__
if constexpr (is_atomic) {
mac_os_atomic_fetch_add(&label_val, value);
}
else {
label_val += value;
}
#else
label_val += value;
#endif
} break;
case op_type_t::DEC:
#ifdef __APPLE__
if constexpr (is_atomic) {
mac_os_atomic_fetch_sub(&label_val, value);
}
else {
label_val -= value;
}

#else
label_val -= value;
#endif
break;
case op_type_t::SET:
label_val = value;
break;
}
}

std::map<std::vector<std::string>, std::atomic<double>,
std::less<std::vector<std::string>>>
atomic_value_map_;
std::atomic<double> default_lable_value_ = 0;

std::mutex mtx_;
std::map<std::vector<std::string>, double,
std::less<std::vector<std::string>>>
value_map_;
};
} // namespace ylt
Loading
Loading