diff --git a/demo/test_client.cpp b/demo/test_client.cpp index 9320305..e3c6c33 100644 --- a/demo/test_client.cpp +++ b/demo/test_client.cpp @@ -10,6 +10,8 @@ int main(void) statsd::StatsdClient client; statsd::StatsdClient client2("127.0.0.1", 8125, "myproject.abx."); + client.event({"An error occurred", "Error message", statsd::Event::Type::error, {"env:dev"}}); + client.count("count1", 123, 1.0); client.count("count2", 125, 1.0); client.gauge("speed", 10); diff --git a/src/statsd_client.cpp b/src/statsd_client.cpp index 9f04e32..4063502 100644 --- a/src/statsd_client.cpp +++ b/src/statsd_client.cpp @@ -25,6 +25,69 @@ using namespace std; namespace statsd { +Event::Event(std::string title, std::string text, Event::Type type, tags_t tags) + : title_{title} + , text_{text} + , type_{type} + , tags_{tags} +{} + +std::string Event::serialize() const +{ + std::string message; + + const auto e_text = [&]{ + std::string str; + for (const char c : text_) + { + if (c == '\n') + str.append("\\n"); + else + str.push_back(c); + } + return str; + }(); + + message += "_e{" + std::to_string(title_.size()) + "," + std::to_string(e_text.size()) + "}:" + title_ + "|" + e_text; + + if (timestamp_ != 0) + message += "|d:" + std::to_string(timestamp_); + + if (hostname_ != "") + message += "|h:" + hostname_; + + if (aggregation_Key_ != "") + message += "|k:" + aggregation_Key_; + + switch (priority_) + { + case Priority::low: message += "|p:low"; break; + case Priority::normal: message += "|p:normal"; break; + } + + if (source_type_name_ != "") + message += "|s:" + source_type_name_; + + switch (type_) + { + case Type::info: message += "|t:info"; break; + case Type::success: message += "|t:success"; break; + case Type::warning: message += "|t:warning"; break; + case Type::error: message += "|t:error"; break; + } + + if (!tags_.empty()) { + message += "|#"; + for(std::size_t i = 0, size = tags_.size(); i < size; ++i) { + message += tags_[i]; + if (i < size - 1) + message += ","; + } + } + + return message; +} + inline bool fequal(float a, float b) { const float epsilon = 0.0001; @@ -164,6 +227,11 @@ int StatsdClient::timing(const string& key, size_t ms, float sample_rate, tags_t return send(key, ms, "ms", sample_rate, tags); } +int StatsdClient::event(const Event& event) +{ + return send(event.serialize()); +} + int StatsdClient::send(string key, size_t value, const string &type, float sample_rate, tags_t tags) { if (!should_send(this->d, sample_rate)) { diff --git a/src/statsd_client.h b/src/statsd_client.h index d57d78f..7fe7d02 100644 --- a/src/statsd_client.h +++ b/src/statsd_client.h @@ -9,6 +9,45 @@ namespace statsd { +class Event{ + public: + enum class Type{ + info, + success, + warning, + error + }; + + enum class Priority{ + normal, + low + }; + + using tags_t = std::vector; + + private: + std::string title_; + std::string text_; + unsigned int timestamp_{0}; + std::string hostname_; + std::string aggregation_Key_; + Priority priority_ {Priority::normal}; + std::string source_type_name_; + Type type_ {Type::info}; + tags_t tags_; + + public: + Event(std::string title, std::string text, Type type = Type::info, tags_t tags = tags_t{}); + + void set_timestamp(unsigned int timestamp){ timestamp_ = timestamp; } + void set_hostname(std::string hostname){ hostname_ = hostname; } + void set_aggregation_Key(std::string aggregation_Key){ aggregation_Key_ = aggregation_Key; } + void set_priority(Priority priority){ priority_ = priority; } + void set_source_type_name(std::string source_type_name){ source_type_name_ = source_type_name; } + + std::string serialize() const; +}; + struct _StatsdClientData; class StatsdClient { @@ -29,6 +68,7 @@ class StatsdClient { int count(const std::string& key, size_t value, float sample_rate = 1.0, tags_t = tags_t(0)); int gauge(const std::string& key, size_t value, float sample_rate = 1.0, tags_t = tags_t(0)); int timing(const std::string& key, size_t ms, float sample_rate = 1.0, tags_t = tags_t(0)); + int event(const Event& event); public: /**