1 | #pragma once |
2 | |
3 | #include <string> |
4 | #include <time.h> |
5 | #include <Poco/Net/StreamSocket.h> |
6 | #include <Poco/Net/SocketStream.h> |
7 | #include <Poco/Util/Application.h> |
8 | #include <common/logger_useful.h> |
9 | |
10 | |
11 | /// пишет в Graphite данные в формате |
12 | /// path value timestamp\n |
13 | /// path может иметь любую вложенность. Директории разделяются с помощью "." |
14 | /// у нас принят следующий формат path - root_path.server_name.sub_path.key |
15 | class GraphiteWriter |
16 | { |
17 | public: |
18 | GraphiteWriter(const std::string & config_name, const std::string & sub_path = "" ); |
19 | |
20 | template <typename T> using KeyValuePair = std::pair<std::string, T>; |
21 | template <typename T> using KeyValueVector = std::vector<KeyValuePair<T>>; |
22 | |
23 | template <typename T> void write(const std::string & key, const T & value, |
24 | time_t timestamp = 0, const std::string & custom_root_path = "" ) |
25 | { |
26 | writeImpl(KeyValuePair<T>{ key, value }, timestamp, custom_root_path); |
27 | } |
28 | |
29 | template <typename T> void write(const KeyValueVector<T> & key_val_vec, |
30 | time_t timestamp = 0, const std::string & custom_root_path = "" ) |
31 | { |
32 | writeImpl(key_val_vec, timestamp, custom_root_path); |
33 | } |
34 | |
35 | /// возвращает путь root_path.server_name |
36 | static std::string getPerServerPath(const std::string & server_name, const std::string & root_path = "one_min" ); |
37 | private: |
38 | template <typename T> |
39 | void writeImpl(const T & data, time_t timestamp, const std::string & custom_root_path) |
40 | { |
41 | if (!timestamp) |
42 | timestamp = time(nullptr); |
43 | |
44 | try |
45 | { |
46 | Poco::Net::SocketAddress socket_address(host, port); |
47 | Poco::Net::StreamSocket socket(socket_address); |
48 | socket.setSendTimeout(Poco::Timespan(timeout * 1000000)); |
49 | Poco::Net::SocketStream str(socket); |
50 | |
51 | out(str, data, timestamp, custom_root_path); |
52 | } |
53 | catch (const Poco::Exception & e) |
54 | { |
55 | LOG_WARNING(&Poco::Util::Application::instance().logger(), |
56 | "Fail to write to Graphite " << host << ":" << port << ". e.what() = " << e.what() << ", e.message() = " << e.message()); |
57 | } |
58 | } |
59 | |
60 | template <typename T> |
61 | void out(std::ostream & os, const KeyValuePair<T> & key_val, time_t timestamp, const std::string & custom_root_path) |
62 | { |
63 | os << (custom_root_path.empty() ? root_path : custom_root_path) << |
64 | '.' << key_val.first << ' ' << key_val.second << ' ' << timestamp << '\n'; |
65 | } |
66 | |
67 | template <typename T> |
68 | void out(std::ostream & os, const KeyValueVector<T> & key_val_vec, time_t timestamp, const std::string & custom_root_path) |
69 | { |
70 | for (const auto & key_val : key_val_vec) |
71 | out(os, key_val, timestamp, custom_root_path); |
72 | } |
73 | |
74 | std::string root_path; |
75 | |
76 | int port; |
77 | std::string host; |
78 | double timeout; |
79 | }; |
80 | |