// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // Author: Ge,Jun (gejun@baidu.com) // Date: 2014/09/22 11:57:43 #ifndef BVAR_LATENCY_RECORDER_H #define BVAR_LATENCY_RECORDER_H #include "bvar/recorder.h" #include "bvar/reducer.h" #include "bvar/passive_status.h" #include "bvar/detail/percentile.h" namespace bvar { namespace detail { class Percentile; typedef Window<IntRecorder, SERIES_IN_SECOND> RecorderWindow; typedef Window<Maxer<int64_t>, SERIES_IN_SECOND> MaxWindow; typedef Window<Percentile, SERIES_IN_SECOND> PercentileWindow; // NOTE: Always use int64_t in the interfaces no matter what the impl. is. class CDF : public Variable { public: explicit CDF(PercentileWindow* w); ~CDF(); void describe(std::ostream& os, bool quote_string) const override; int describe_series(std::ostream& os, const SeriesOptions& options) const override; private: PercentileWindow* _w; }; // For mimic constructor inheritance. class LatencyRecorderBase { public: explicit LatencyRecorderBase(time_t window_size); time_t window_size() const { return _latency_window.window_size(); } protected: IntRecorder _latency; Maxer<int64_t> _max_latency; Percentile _latency_percentile; RecorderWindow _latency_window; MaxWindow _max_latency_window; PassiveStatus<int64_t> _count; PassiveStatus<int64_t> _qps; PercentileWindow _latency_percentile_window; PassiveStatus<int64_t> _latency_p1; PassiveStatus<int64_t> _latency_p2; PassiveStatus<int64_t> _latency_p3; PassiveStatus<int64_t> _latency_999; // 99.9% PassiveStatus<int64_t> _latency_9999; // 99.99% CDF _latency_cdf; PassiveStatus<Vector<int64_t, 4> > _latency_percentiles; }; } // namespace detail // Specialized structure to record latency. // It's not a Variable, but it contains multiple bvar inside. class LatencyRecorder : public detail::LatencyRecorderBase { typedef detail::LatencyRecorderBase Base; public: LatencyRecorder() : Base(-1) {} explicit LatencyRecorder(time_t window_size) : Base(window_size) {} explicit LatencyRecorder(const butil::StringPiece& prefix) : Base(-1) { expose(prefix); } LatencyRecorder(const butil::StringPiece& prefix, time_t window_size) : Base(window_size) { expose(prefix); } LatencyRecorder(const butil::StringPiece& prefix1, const butil::StringPiece& prefix2) : Base(-1) { expose(prefix1, prefix2); } LatencyRecorder(const butil::StringPiece& prefix1, const butil::StringPiece& prefix2, time_t window_size) : Base(window_size) { expose(prefix1, prefix2); } ~LatencyRecorder() { hide(); } // Record the latency. LatencyRecorder& operator<<(int64_t latency); // Expose all internal variables using `prefix' as prefix. // Returns 0 on success, -1 otherwise. // Example: // LatencyRecorder rec; // rec.expose("foo_bar_write"); // foo_bar_write_latency // // foo_bar_write_max_latency // // foo_bar_write_count // // foo_bar_write_qps // rec.expose("foo_bar", "read"); // foo_bar_read_latency // // foo_bar_read_max_latency // // foo_bar_read_count // // foo_bar_read_qps int expose(const butil::StringPiece& prefix) { return expose(butil::StringPiece(), prefix); } int expose(const butil::StringPiece& prefix1, const butil::StringPiece& prefix2); // Hide all internal variables, called in dtor as well. void hide(); // Get the average latency in recent |window_size| seconds // If |window_size| is absent, use the window_size to ctor. int64_t latency(time_t window_size) const { return _latency_window.get_value(window_size).get_average_int(); } int64_t latency() const { return _latency_window.get_value().get_average_int(); } // Get p1/p2/p3/99.9-ile latencies in recent window_size-to-ctor seconds. Vector<int64_t, 4> latency_percentiles() const; // Get the max latency in recent window_size-to-ctor seconds. int64_t max_latency() const { return _max_latency_window.get_value(); } // Get the total number of recorded latencies. int64_t count() const { return _latency.get_value().num; } // Get qps in recent |window_size| seconds. The `q' means latencies // recorded by operator<<(). // If |window_size| is absent, use the window_size to ctor. int64_t qps(time_t window_size) const; int64_t qps() const { return _qps.get_value(); } // Get |ratio|-ile latency in recent |window_size| seconds // E.g. 0.99 means 99%-ile int64_t latency_percentile(double ratio) const; // Get name of a sub-bvar. const std::string& latency_name() const { return _latency_window.name(); } const std::string& latency_percentiles_name() const { return _latency_percentiles.name(); } const std::string& latency_cdf_name() const { return _latency_cdf.name(); } const std::string& max_latency_name() const { return _max_latency_window.name(); } const std::string& count_name() const { return _count.name(); } const std::string& qps_name() const { return _qps.name(); } }; std::ostream& operator<<(std::ostream& os, const LatencyRecorder&); } // namespace bvar #endif //BVAR_LATENCY_RECORDER_H