encode.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include "encode.h"
  2. #include <library/cpp/monlib/encode/encoder.h>
  3. #include <library/cpp/monlib/encode/json/json.h>
  4. #include <library/cpp/monlib/encode/spack/spack_v1.h>
  5. #include <library/cpp/monlib/encode/prometheus/prometheus.h>
  6. #include <util/stream/str.h>
  7. namespace NMonitoring {
  8. namespace {
  9. constexpr TInstant ZERO_TIME = TInstant::Zero();
  10. class TConsumer final: public ICountableConsumer {
  11. using TLabel = std::pair<TString, TString>; // name, value
  12. public:
  13. explicit TConsumer(NMonitoring::IMetricEncoderPtr encoderImpl, TCountableBase::EVisibility vis)
  14. : EncoderImpl_(std::move(encoderImpl))
  15. , Visibility_{vis}
  16. {
  17. }
  18. void OnCounter(
  19. const TString& labelName, const TString& labelValue,
  20. const TCounterForPtr* counter) override {
  21. NMonitoring::EMetricType metricType = counter->ForDerivative()
  22. ? NMonitoring::EMetricType::RATE
  23. : NMonitoring::EMetricType::GAUGE;
  24. EncoderImpl_->OnMetricBegin(metricType);
  25. EncodeLabels(labelName, labelValue);
  26. if (metricType == NMonitoring::EMetricType::GAUGE) {
  27. EncoderImpl_->OnDouble(ZERO_TIME, static_cast<double>(counter->Val()));
  28. } else {
  29. EncoderImpl_->OnUint64(ZERO_TIME, counter->Val());
  30. }
  31. EncoderImpl_->OnMetricEnd();
  32. }
  33. void OnHistogram(
  34. const TString& labelName, const TString& labelValue,
  35. IHistogramSnapshotPtr snapshot, bool derivative) override {
  36. NMonitoring::EMetricType metricType = derivative ? EMetricType::HIST_RATE : EMetricType::HIST;
  37. EncoderImpl_->OnMetricBegin(metricType);
  38. EncodeLabels(labelName, labelValue);
  39. EncoderImpl_->OnHistogram(ZERO_TIME, snapshot);
  40. EncoderImpl_->OnMetricEnd();
  41. }
  42. void OnGroupBegin(
  43. const TString& labelName, const TString& labelValue,
  44. const TDynamicCounters*) override {
  45. if (labelName.empty() && labelValue.empty()) {
  46. // root group has empty label name and value
  47. EncoderImpl_->OnStreamBegin();
  48. } else {
  49. ParentLabels_.emplace_back(labelName, labelValue);
  50. }
  51. }
  52. void OnGroupEnd(
  53. const TString& labelName, const TString& labelValue,
  54. const TDynamicCounters*) override {
  55. if (labelName.empty() && labelValue.empty()) {
  56. // root group has empty label name and value
  57. EncoderImpl_->OnStreamEnd();
  58. EncoderImpl_->Close();
  59. } else {
  60. ParentLabels_.pop_back();
  61. }
  62. }
  63. TCountableBase::EVisibility Visibility() const override {
  64. return Visibility_;
  65. }
  66. private:
  67. void EncodeLabels(const TString& labelName, const TString& labelValue) {
  68. EncoderImpl_->OnLabelsBegin();
  69. for (const auto& label : ParentLabels_) {
  70. EncoderImpl_->OnLabel(label.first, label.second);
  71. }
  72. EncoderImpl_->OnLabel(labelName, labelValue);
  73. EncoderImpl_->OnLabelsEnd();
  74. }
  75. private:
  76. NMonitoring::IMetricEncoderPtr EncoderImpl_;
  77. TVector<TLabel> ParentLabels_;
  78. TCountableBase::EVisibility Visibility_;
  79. };
  80. }
  81. THolder<ICountableConsumer> CreateEncoder(IOutputStream* out, EFormat format, TCountableBase::EVisibility vis) {
  82. switch (format) {
  83. case EFormat::JSON:
  84. return MakeHolder<TConsumer>(NMonitoring::EncoderJson(out), vis);
  85. case EFormat::SPACK:
  86. return MakeHolder<TConsumer>(NMonitoring::EncoderSpackV1(
  87. out,
  88. NMonitoring::ETimePrecision::SECONDS,
  89. NMonitoring::ECompression::ZSTD), vis);
  90. case EFormat::PROMETHEUS:
  91. return MakeHolder<TConsumer>(NMonitoring::EncoderPrometheus(
  92. out), vis);
  93. default:
  94. ythrow yexception() << "unsupported metric encoding format: " << format;
  95. break;
  96. }
  97. }
  98. THolder<ICountableConsumer> AsCountableConsumer(IMetricEncoderPtr encoder, TCountableBase::EVisibility visibility) {
  99. return MakeHolder<TConsumer>(std::move(encoder), visibility);
  100. }
  101. void ToJson(const TDynamicCounters& counters, IOutputStream* out) {
  102. TConsumer consumer{EncoderJson(out), TCountableBase::EVisibility::Public};
  103. counters.Accept(TString{}, TString{}, consumer);
  104. }
  105. TString ToJson(const TDynamicCounters& counters) {
  106. TStringStream ss;
  107. ToJson(counters, &ss);
  108. return ss.Str();
  109. }
  110. }