encode.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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,
  82. TStringBuf nameLabel, TCountableBase::EVisibility vis)
  83. {
  84. switch (format) {
  85. case EFormat::JSON:
  86. return MakeHolder<TConsumer>(NMonitoring::EncoderJson(out), vis);
  87. case EFormat::SPACK:
  88. return MakeHolder<TConsumer>(NMonitoring::EncoderSpackV1(
  89. out,
  90. NMonitoring::ETimePrecision::SECONDS,
  91. NMonitoring::ECompression::ZSTD), vis);
  92. case EFormat::PROMETHEUS:
  93. return MakeHolder<TConsumer>(NMonitoring::EncoderPrometheus(
  94. out, nameLabel), vis);
  95. default:
  96. ythrow yexception() << "unsupported metric encoding format: " << format;
  97. break;
  98. }
  99. }
  100. THolder<ICountableConsumer> AsCountableConsumer(IMetricEncoderPtr encoder, TCountableBase::EVisibility visibility) {
  101. return MakeHolder<TConsumer>(std::move(encoder), visibility);
  102. }
  103. void ToJson(const TDynamicCounters& counters, IOutputStream* out) {
  104. TConsumer consumer{EncoderJson(out), TCountableBase::EVisibility::Public};
  105. counters.Accept(TString{}, TString{}, consumer);
  106. }
  107. TString ToJson(const TDynamicCounters& counters) {
  108. TStringStream ss;
  109. ToJson(counters, &ss);
  110. return ss.Str();
  111. }
  112. }