#pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace NSimpleHistogram { template class THistogram { public: explicit THistogram(TVector&& values) : Values_(std::move(values)) { } size_t TotalCount() const { return Values_.size(); } T ValueAtPercentile(double percentile) const { Y_ASSERT(!Values_.empty()); Y_ASSERT(percentile >= 0.0 && percentile <= 1.0); const size_t index = static_cast(percentile * Values_.size()); return Values_[Min(Values_.size() - 1, index)]; } private: TVector Values_; }; template class THistogramCalcer { public: size_t TotalCount() const { return Values_.size(); } void Reserve(size_t cnt) { Values_.reserve(cnt); } void RecordValue(T value) { Values_.push_back(value); } THistogram Calc() { if (!IsSorted(Values_.begin(), Values_.end())) { Sort(Values_.begin(), Values_.end()); } return THistogram(std::move(Values_)); } private: TVector Values_; }; template class TMultiHistogramCalcer { public: void RecordValue(TStringBuf name, T value) { Calcers_[name].RecordValue(value); } THashMap> Calc() { THashMap> result; for (auto& calcer : Calcers_) { result.emplace(calcer.first, calcer.second.Calc()); } return result; } private: THashMap> Calcers_; }; template class TThreadSafeMultiHistogramCalcer { public: void RecordValue(TStringBuf name, T value) { TGuard guard(Mutex_); Calcer_.RecordValue(name, value); } THashMap> Calc() { return Calcer_.Calc(); } private: TMutex Mutex_; TMultiHistogramCalcer Calcer_; }; template NJson::TJsonValue ToJson(const THistogram& hist, const TVector& percentiles) { NJson::TJsonValue json; for (double percentile : percentiles) { TStringBuilder name; name << "Q" << Prec(percentile * 100, PREC_POINT_DIGITS_STRIP_ZEROES, 2); json[name] = hist.ValueAtPercentile(percentile); } json["RecordCount"] = hist.TotalCount(); return json; } template NJson::TJsonValue ToJson(const THashMap>& hists, const TVector& percentiles) { NJson::TJsonValue json; for (const auto& p : hists) { json[p.first] = ToJson(p.second, percentiles); } return json; } template TString ToJsonStr(const THashMap>& hists, const TVector& percentiles, bool format = true) { NJson::TJsonValue json = ToJson(hists, percentiles); NJsonWriter::TBuf buf; if (format) { buf.SetIndentSpaces(4); } return buf.WriteJsonValue(&json, true).Str(); } }