Skip to content

Commit

Permalink
[new feature]Add metrics (#674)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Jun 7, 2024
1 parent 9d29664 commit c000609
Show file tree
Hide file tree
Showing 20 changed files with 2,169 additions and 43 deletions.
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/msvc-dev-cmd@v1.12.0
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/ccache-action@v1.2
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/msvc-dev-cmd@v1.12.0
# 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/ccache-action@v1.2
# 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

0 comments on commit c000609

Please sign in to comment.