-
Notifications
You must be signed in to change notification settings - Fork 110
[k2] add metrics builder and k2_write_metric API #1639
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
Open
denisichh
wants to merge
7
commits into
master
Choose a base branch
from
dzubarev/common-logs-api-k2kphp
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+239
−0
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
694884f
first version
denisichh 2b7be26
added metric builder + write_serialized_metric to k2-api
denisichh 7bb602d
v1.0
denisichh f6af9d2
v1.1
denisichh 0608cf2
rename
denisichh 12b21ac
mask size 32bits to 8bits
denisichh 5bb69d9
fixes
denisichh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,201 @@ | ||
| // Compiler for PHP (aka KPHP) | ||
| // Copyright (c) 2026 LLC «V Kontakte» | ||
| // Distributed under the GPL v3 License, see LICENSE.notice.txt | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <chrono> | ||
| #include <cstddef> | ||
| #include <cstdint> | ||
| #include <expected> | ||
| #include <initializer_list> | ||
| #include <memory> | ||
| #include <string_view> | ||
|
|
||
| #include "common/containers/final_action.h" | ||
| #include "common/mixin/movable_only.h" | ||
| #include "runtime-common/core/allocator/script-allocator.h" | ||
| #include "runtime-common/core/std/containers.h" | ||
| #include "runtime-light/k2-platform/k2-api.h" | ||
|
|
||
| namespace kphp::diagnostics { | ||
| struct MetricBuilder final : vk::movable_only { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's put it in |
||
| public: | ||
| using bytes_vector = kphp::stl::vector<std::byte, kphp::memory::script_allocator>; | ||
|
|
||
| private: | ||
| using string = kphp::stl::string<kphp::memory::script_allocator>; | ||
|
|
||
| string metric_name; | ||
| kphp::stl::vector<std::pair<string, string>, kphp::memory::script_allocator> tags; | ||
| size_t msg_size{0}; | ||
|
|
||
| explicit MetricBuilder(std::string_view metric_name) noexcept | ||
| : metric_name{metric_name} { | ||
| this->msg_size += MetricBuilder::string_sizeof(metric_name); | ||
| } | ||
|
|
||
| template<typename T> | ||
| requires std::is_arithmetic_v<T> | ||
| static void store_number(bytes_vector& buf, const T& number) noexcept { | ||
| const auto* src{static_cast<const std::byte*>(static_cast<const void*>(std::addressof(number)))}; | ||
| buf.insert(buf.end(), src, src + sizeof(T)); | ||
| } | ||
|
|
||
| static void store_string(bytes_vector& buf, const std::string_view& string) noexcept { | ||
| MetricBuilder::store_number(buf, string.size()); | ||
| std::transform(string.begin(), string.end(), std::back_inserter(buf), [](char c) { return std::byte(c); }); | ||
| } | ||
|
|
||
| static void store_tag(bytes_vector& buf, std::pair<std::string_view, std::string_view> tag) noexcept { | ||
| MetricBuilder::store_string(buf, tag.first); | ||
| MetricBuilder::store_string(buf, tag.second); | ||
| } | ||
|
|
||
| void store_msg(bytes_vector& buf) const noexcept { | ||
| MetricBuilder::store_number(buf, this->msg_size); | ||
| MetricBuilder::store_string(buf, std::string_view{this->metric_name.c_str(), this->metric_name.size()}); | ||
| for (const auto& [tag_name, tag_value] : this->tags) { | ||
| MetricBuilder::store_tag(buf, {std::string_view{tag_name.c_str(), tag_name.size()}, std::string_view{tag_value.c_str(), tag_value.size()}}); | ||
| } | ||
| } | ||
|
|
||
| auto send_helper(const std::initializer_list<std::pair<std::string_view, std::string_view>>& tags) noexcept { | ||
| size_t tags_size{}; | ||
| for (const auto& [tag_name, tag_value] : tags) { | ||
| tags_size += MetricBuilder::string_sizeof(tag_name) + MetricBuilder::string_sizeof(tag_value); | ||
| } | ||
| this->msg_size += tags_size; | ||
| return vk::final_action{[tags_size, this]() { this->msg_size -= tags_size; }}; | ||
| } | ||
|
|
||
| static size_t string_sizeof(const std::string_view& string) noexcept { | ||
| return sizeof(size_t) + string.size(); | ||
| } | ||
|
|
||
| static uint32_t s_timestamp_now() noexcept { | ||
| return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count(); | ||
| } | ||
|
|
||
| public: | ||
| static std::expected<void, int32_t> send(bytes_vector& buf, k2::MonitoringSystem ms) noexcept { | ||
| return k2::write_metric(std::span{buf.data(), buf.size()}, ms); | ||
| } | ||
|
|
||
| static MetricBuilder metric(std::string_view metric_name) noexcept { | ||
| return MetricBuilder{metric_name}; | ||
| } | ||
|
|
||
| MetricBuilder& tag(std::string_view tag_name, std::string_view tag_value) noexcept { | ||
| this->tags.emplace_back(tag_name, tag_value); | ||
| this->msg_size += MetricBuilder::string_sizeof(tag_name) + MetricBuilder::string_sizeof(tag_value); | ||
| return *this; | ||
| } | ||
|
|
||
| bytes_vector build_value(double value, std::optional<uint32_t> timestamp = std::nullopt) const noexcept { | ||
| bytes_vector buf{}; | ||
| buf.reserve(sizeof(uint32_t) + sizeof(uint8_t) + sizeof(double) + sizeof(size_t) + | ||
| this->msg_size); // timestamp_u32 + value_kind_u8 + value_f64 + msg_size_usize + msg_len | ||
|
|
||
| uint32_t s_timestamp{timestamp.value_or(MetricBuilder::s_timestamp_now())}; | ||
|
|
||
| MetricBuilder::store_number(buf, s_timestamp); | ||
| MetricBuilder::store_number(buf, static_cast<uint8_t>(k2::MetricValueKind::VALUE)); | ||
| MetricBuilder::store_number(buf, value); | ||
| this->store_msg(buf); | ||
| return buf; | ||
| } | ||
|
|
||
| bytes_vector build_values_array(std::initializer_list<double> values, std::optional<uint32_t> timestamp = std::nullopt) const noexcept { | ||
| bytes_vector buf{}; | ||
| buf.reserve(sizeof(uint32_t) + sizeof(uint8_t) + sizeof(size_t) + sizeof(double) * values.size() + sizeof(size_t) + | ||
| this->msg_size); // timestamp_u32 + value_kind_u8 + array_len_usize + value_f64*array_len + msg_size_usize + msg_len | ||
|
|
||
| uint32_t s_timestamp{timestamp.value_or(MetricBuilder::s_timestamp_now())}; | ||
|
|
||
| MetricBuilder::store_number(buf, s_timestamp); | ||
| MetricBuilder::store_number(buf, static_cast<uint8_t>(k2::MetricValueKind::VALUES_ARRAY)); | ||
| MetricBuilder::store_number(buf, values.size()); | ||
| for (const auto& value : values) { | ||
| MetricBuilder::store_number(buf, value); | ||
| } | ||
| this->store_msg(buf); | ||
| return buf; | ||
| } | ||
|
|
||
| bytes_vector build_count(double count, std::optional<uint32_t> timestamp = std::nullopt) const noexcept { | ||
| bytes_vector buf{}; | ||
| buf.reserve(sizeof(uint32_t) + sizeof(uint8_t) + sizeof(double) + sizeof(size_t) + | ||
| this->msg_size); // timestamp_u32 + value_kind_u8 + count_f64 + msg_size_usize + msg_len | ||
|
|
||
| uint32_t s_timestamp{timestamp.value_or(MetricBuilder::s_timestamp_now())}; | ||
|
|
||
| MetricBuilder::store_number(buf, s_timestamp); | ||
| MetricBuilder::store_number(buf, static_cast<uint8_t>(k2::MetricValueKind::COUNT)); | ||
| MetricBuilder::store_number(buf, count); | ||
| this->store_msg(buf); | ||
| return buf; | ||
| } | ||
|
|
||
| bytes_vector build_increment(std::optional<uint32_t> timestamp = std::nullopt) const noexcept { | ||
| bytes_vector buf{}; | ||
| buf.reserve(sizeof(uint32_t) + sizeof(uint8_t) + sizeof(size_t) + this->msg_size); // timestamp_u32 + value_kind_u8 + msg_size_usize + msg_len | ||
|
|
||
| uint32_t s_timestamp{timestamp.value_or(MetricBuilder::s_timestamp_now())}; | ||
|
|
||
| MetricBuilder::store_number(buf, s_timestamp); | ||
| MetricBuilder::store_number(buf, static_cast<uint8_t>(k2::MetricValueKind::INC)); | ||
| this->store_msg(buf); | ||
| return buf; | ||
| } | ||
|
|
||
| std::expected<void, int32_t> send_value(double value, k2::MonitoringSystem ms, std::initializer_list<std::pair<std::string_view, std::string_view>> tags = {}, | ||
| std::optional<uint32_t> timestamp = std::nullopt) noexcept { | ||
| auto final_action{send_helper(tags)}; | ||
|
|
||
| auto buf{this->build_value(value, timestamp)}; | ||
| for (const auto& tag : tags) { | ||
| MetricBuilder::store_tag(buf, tag); | ||
| } | ||
|
|
||
| return MetricBuilder::send(buf, ms); | ||
| } | ||
|
|
||
| std::expected<void, int32_t> send_values_array(std::initializer_list<double> values, k2::MonitoringSystem ms, | ||
| std::initializer_list<std::pair<std::string_view, std::string_view>> tags = {}, | ||
| std::optional<uint32_t> timestamp = std::nullopt) noexcept { | ||
| auto final_action{send_helper(tags)}; | ||
|
|
||
| auto buf{this->build_values_array(values, timestamp)}; | ||
| for (const auto& tag : tags) { | ||
| MetricBuilder::store_tag(buf, tag); | ||
| } | ||
|
|
||
| return MetricBuilder::send(buf, ms); | ||
| } | ||
|
|
||
| std::expected<void, int32_t> send_count(double count, k2::MonitoringSystem ms, std::initializer_list<std::pair<std::string_view, std::string_view>> tags = {}, | ||
| std::optional<uint32_t> timestamp = std::nullopt) noexcept { | ||
| auto final_action{send_helper(tags)}; | ||
|
|
||
| auto buf{this->build_count(count, timestamp)}; | ||
| for (const auto& tag : tags) { | ||
| MetricBuilder::store_tag(buf, tag); | ||
| } | ||
|
|
||
| return MetricBuilder::send(buf, ms); | ||
| } | ||
|
|
||
| std::expected<void, int32_t> send_increment(k2::MonitoringSystem ms, std::initializer_list<std::pair<std::string_view, std::string_view>> tags = {}, | ||
| std::optional<uint32_t> timestamp = std::nullopt) noexcept { | ||
| auto final_action{send_helper(tags)}; | ||
|
|
||
| auto buf{this->build_increment(timestamp)}; | ||
| for (const auto& tag : tags) { | ||
| MetricBuilder::store_tag(buf, tag); | ||
| } | ||
|
|
||
| return MetricBuilder::send(buf, ms); | ||
| } | ||
| }; | ||
| } // namespace kphp::diagnostics | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is
msg_size? Let's add a more detailed descriptionThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done