text_encoder.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include "text.h"
  2. #include <library/cpp/monlib/encode/encoder_state.h>
  3. #include <library/cpp/monlib/metrics/labels.h>
  4. #include <library/cpp/monlib/metrics/metric_value.h>
  5. #include <util/datetime/base.h>
  6. #include <util/stream/format.h>
  7. namespace NMonitoring {
  8. namespace {
  9. class TEncoderText final: public IMetricEncoder {
  10. public:
  11. TEncoderText(IOutputStream* out, bool humanReadableTs)
  12. : Out_(out)
  13. , HumanReadableTs_(humanReadableTs)
  14. {
  15. }
  16. private:
  17. void OnStreamBegin() override {
  18. State_.Expect(TEncoderState::EState::ROOT);
  19. }
  20. void OnStreamEnd() override {
  21. State_.Expect(TEncoderState::EState::ROOT);
  22. }
  23. void OnCommonTime(TInstant time) override {
  24. State_.Expect(TEncoderState::EState::ROOT);
  25. CommonTime_ = time;
  26. if (time != TInstant::Zero()) {
  27. Out_->Write(TStringBuf("common time: "));
  28. WriteTime(time);
  29. Out_->Write('\n');
  30. }
  31. }
  32. void OnMetricBegin(EMetricType type) override {
  33. State_.Switch(TEncoderState::EState::ROOT, TEncoderState::EState::METRIC);
  34. ClearLastMetricState();
  35. MetricType_ = type;
  36. }
  37. void OnMetricEnd() override {
  38. State_.Switch(TEncoderState::EState::METRIC, TEncoderState::EState::ROOT);
  39. WriteMetric();
  40. }
  41. void OnLabelsBegin() override {
  42. if (State_ == TEncoderState::EState::METRIC) {
  43. State_ = TEncoderState::EState::METRIC_LABELS;
  44. } else if (State_ == TEncoderState::EState::ROOT) {
  45. State_ = TEncoderState::EState::COMMON_LABELS;
  46. } else {
  47. State_.ThrowInvalid("expected METRIC or ROOT");
  48. }
  49. }
  50. void OnLabelsEnd() override {
  51. if (State_ == TEncoderState::EState::METRIC_LABELS) {
  52. State_ = TEncoderState::EState::METRIC;
  53. } else if (State_ == TEncoderState::EState::COMMON_LABELS) {
  54. State_ = TEncoderState::EState::ROOT;
  55. Out_->Write(TStringBuf("common labels: "));
  56. WriteLabels();
  57. Out_->Write('\n');
  58. } else {
  59. State_.ThrowInvalid("expected LABELS or COMMON_LABELS");
  60. }
  61. }
  62. void OnLabel(TStringBuf name, TStringBuf value) override {
  63. Labels_.Add(name, value);
  64. }
  65. void OnDouble(TInstant time, double value) override {
  66. State_.Expect(TEncoderState::EState::METRIC);
  67. TimeSeries_.Add(time, value);
  68. }
  69. void OnInt64(TInstant time, i64 value) override {
  70. State_.Expect(TEncoderState::EState::METRIC);
  71. TimeSeries_.Add(time, value);
  72. }
  73. void OnUint64(TInstant time, ui64 value) override {
  74. State_.Expect(TEncoderState::EState::METRIC);
  75. TimeSeries_.Add(time, value);
  76. }
  77. void OnHistogram(TInstant time, IHistogramSnapshotPtr snapshot) override {
  78. State_.Expect(TEncoderState::EState::METRIC);
  79. TimeSeries_.Add(time, snapshot.Get());
  80. }
  81. void OnSummaryDouble(TInstant time, ISummaryDoubleSnapshotPtr snapshot) override {
  82. State_.Expect(TEncoderState::EState::METRIC);
  83. TimeSeries_.Add(time, snapshot.Get());
  84. }
  85. void OnLogHistogram(TInstant ts, TLogHistogramSnapshotPtr snapshot) override {
  86. State_.Expect(TEncoderState::EState::METRIC);
  87. TimeSeries_.Add(ts, snapshot.Get());
  88. }
  89. void Close() override {
  90. }
  91. void WriteTime(TInstant time) {
  92. if (HumanReadableTs_) {
  93. char buf[64];
  94. auto len = FormatDate8601(buf, sizeof(buf), time.TimeT());
  95. Out_->Write(buf, len);
  96. } else {
  97. (*Out_) << time.Seconds();
  98. }
  99. }
  100. void WriteValue(EMetricValueType type, TMetricValue value) {
  101. switch (type) {
  102. case EMetricValueType::DOUBLE:
  103. (*Out_) << value.AsDouble();
  104. break;
  105. case EMetricValueType::INT64:
  106. (*Out_) << value.AsInt64();
  107. break;
  108. case EMetricValueType::UINT64:
  109. (*Out_) << value.AsUint64();
  110. break;
  111. case EMetricValueType::HISTOGRAM:
  112. (*Out_) << *value.AsHistogram();
  113. break;
  114. case EMetricValueType::SUMMARY:
  115. (*Out_) << *value.AsSummaryDouble();
  116. break;
  117. case EMetricValueType::LOGHISTOGRAM:
  118. (*Out_) << *value.AsLogHistogram();
  119. break;
  120. case EMetricValueType::UNKNOWN:
  121. ythrow yexception() << "unknown metric value type";
  122. }
  123. }
  124. void WriteLabels() {
  125. auto& out = *Out_;
  126. const auto size = Labels_.Size();
  127. size_t i = 0;
  128. out << '{';
  129. for (auto&& l : Labels_) {
  130. out << l.Name() << TStringBuf("='") << l.Value() << '\'';
  131. ++i;
  132. if (i < size) {
  133. out << TStringBuf(", ");
  134. }
  135. };
  136. out << '}';
  137. }
  138. void WriteMetric() {
  139. // (1) type
  140. TStringBuf typeStr = MetricTypeToStr(MetricType_);
  141. (*Out_) << LeftPad(typeStr, MaxMetricTypeNameLength) << ' ';
  142. // (2) name and labels
  143. auto name = Labels_.Extract(TStringBuf("sensor"));
  144. if (name) {
  145. if (name->Value().find(' ') != TString::npos) {
  146. (*Out_) << '"' << name->Value() << '"';
  147. } else {
  148. (*Out_) << name->Value();
  149. }
  150. }
  151. WriteLabels();
  152. // (3) values
  153. if (!TimeSeries_.Empty()) {
  154. TimeSeries_.SortByTs();
  155. Out_->Write(TStringBuf(" ["));
  156. for (size_t i = 0; i < TimeSeries_.Size(); i++) {
  157. if (i > 0) {
  158. Out_->Write(TStringBuf(", "));
  159. }
  160. const auto& point = TimeSeries_[i];
  161. if (point.GetTime() == CommonTime_ || point.GetTime() == TInstant::Zero()) {
  162. WriteValue(TimeSeries_.GetValueType(), point.GetValue());
  163. } else {
  164. Out_->Write('(');
  165. WriteTime(point.GetTime());
  166. Out_->Write(TStringBuf(", "));
  167. WriteValue(TimeSeries_.GetValueType(), point.GetValue());
  168. Out_->Write(')');
  169. }
  170. }
  171. Out_->Write(']');
  172. }
  173. Out_->Write('\n');
  174. }
  175. void ClearLastMetricState() {
  176. MetricType_ = EMetricType::UNKNOWN;
  177. Labels_.Clear();
  178. TimeSeries_.Clear();
  179. }
  180. private:
  181. TEncoderState State_;
  182. IOutputStream* Out_;
  183. bool HumanReadableTs_;
  184. TInstant CommonTime_ = TInstant::Zero();
  185. EMetricType MetricType_ = EMetricType::UNKNOWN;
  186. TLabels Labels_;
  187. TMetricTimeSeries TimeSeries_;
  188. };
  189. }
  190. IMetricEncoderPtr EncoderText(IOutputStream* out, bool humanReadableTs) {
  191. return MakeHolder<TEncoderText>(out, humanReadableTs);
  192. }
  193. }