1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18// Date: 2014/09/22 11:57:43
19
20#ifndef BVAR_LATENCY_RECORDER_H
21#define BVAR_LATENCY_RECORDER_H
22
23#include "bvar/recorder.h"
24#include "bvar/reducer.h"
25#include "bvar/passive_status.h"
26#include "bvar/detail/percentile.h"
27
28namespace bvar {
29namespace detail {
30
31class Percentile;
32typedef Window<IntRecorder, SERIES_IN_SECOND> RecorderWindow;
33typedef Window<Maxer<int64_t>, SERIES_IN_SECOND> MaxWindow;
34typedef Window<Percentile, SERIES_IN_SECOND> PercentileWindow;
35
36// NOTE: Always use int64_t in the interfaces no matter what the impl. is.
37
38class CDF : public Variable {
39public:
40 explicit CDF(PercentileWindow* w);
41 ~CDF();
42 void describe(std::ostream& os, bool quote_string) const override;
43 int describe_series(std::ostream& os, const SeriesOptions& options) const override;
44private:
45 PercentileWindow* _w;
46};
47
48// For mimic constructor inheritance.
49class LatencyRecorderBase {
50public:
51 explicit LatencyRecorderBase(time_t window_size);
52 time_t window_size() const { return _latency_window.window_size(); }
53protected:
54 IntRecorder _latency;
55 Maxer<int64_t> _max_latency;
56 Percentile _latency_percentile;
57
58 RecorderWindow _latency_window;
59 MaxWindow _max_latency_window;
60 PassiveStatus<int64_t> _count;
61 PassiveStatus<int64_t> _qps;
62 PercentileWindow _latency_percentile_window;
63 PassiveStatus<int64_t> _latency_p1;
64 PassiveStatus<int64_t> _latency_p2;
65 PassiveStatus<int64_t> _latency_p3;
66 PassiveStatus<int64_t> _latency_999; // 99.9%
67 PassiveStatus<int64_t> _latency_9999; // 99.99%
68 CDF _latency_cdf;
69 PassiveStatus<Vector<int64_t, 4> > _latency_percentiles;
70};
71} // namespace detail
72
73// Specialized structure to record latency.
74// It's not a Variable, but it contains multiple bvar inside.
75class LatencyRecorder : public detail::LatencyRecorderBase {
76 typedef detail::LatencyRecorderBase Base;
77public:
78 LatencyRecorder() : Base(-1) {}
79 explicit LatencyRecorder(time_t window_size) : Base(window_size) {}
80 explicit LatencyRecorder(const butil::StringPiece& prefix) : Base(-1) {
81 expose(prefix);
82 }
83 LatencyRecorder(const butil::StringPiece& prefix,
84 time_t window_size) : Base(window_size) {
85 expose(prefix);
86 }
87 LatencyRecorder(const butil::StringPiece& prefix1,
88 const butil::StringPiece& prefix2) : Base(-1) {
89 expose(prefix1, prefix2);
90 }
91 LatencyRecorder(const butil::StringPiece& prefix1,
92 const butil::StringPiece& prefix2,
93 time_t window_size) : Base(window_size) {
94 expose(prefix1, prefix2);
95 }
96
97 ~LatencyRecorder() { hide(); }
98
99 // Record the latency.
100 LatencyRecorder& operator<<(int64_t latency);
101
102 // Expose all internal variables using `prefix' as prefix.
103 // Returns 0 on success, -1 otherwise.
104 // Example:
105 // LatencyRecorder rec;
106 // rec.expose("foo_bar_write"); // foo_bar_write_latency
107 // // foo_bar_write_max_latency
108 // // foo_bar_write_count
109 // // foo_bar_write_qps
110 // rec.expose("foo_bar", "read"); // foo_bar_read_latency
111 // // foo_bar_read_max_latency
112 // // foo_bar_read_count
113 // // foo_bar_read_qps
114 int expose(const butil::StringPiece& prefix) {
115 return expose(butil::StringPiece(), prefix);
116 }
117 int expose(const butil::StringPiece& prefix1,
118 const butil::StringPiece& prefix2);
119
120 // Hide all internal variables, called in dtor as well.
121 void hide();
122
123 // Get the average latency in recent |window_size| seconds
124 // If |window_size| is absent, use the window_size to ctor.
125 int64_t latency(time_t window_size) const
126 { return _latency_window.get_value(window_size).get_average_int(); }
127 int64_t latency() const
128 { return _latency_window.get_value().get_average_int(); }
129
130 // Get p1/p2/p3/99.9-ile latencies in recent window_size-to-ctor seconds.
131 Vector<int64_t, 4> latency_percentiles() const;
132
133 // Get the max latency in recent window_size-to-ctor seconds.
134 int64_t max_latency() const { return _max_latency_window.get_value(); }
135
136 // Get the total number of recorded latencies.
137 int64_t count() const { return _latency.get_value().num; }
138
139 // Get qps in recent |window_size| seconds. The `q' means latencies
140 // recorded by operator<<().
141 // If |window_size| is absent, use the window_size to ctor.
142 int64_t qps(time_t window_size) const;
143 int64_t qps() const { return _qps.get_value(); }
144
145 // Get |ratio|-ile latency in recent |window_size| seconds
146 // E.g. 0.99 means 99%-ile
147 int64_t latency_percentile(double ratio) const;
148
149 // Get name of a sub-bvar.
150 const std::string& latency_name() const { return _latency_window.name(); }
151 const std::string& latency_percentiles_name() const
152 { return _latency_percentiles.name(); }
153 const std::string& latency_cdf_name() const { return _latency_cdf.name(); }
154 const std::string& max_latency_name() const
155 { return _max_latency_window.name(); }
156 const std::string& count_name() const { return _count.name(); }
157 const std::string& qps_name() const { return _qps.name(); }
158};
159
160std::ostream& operator<<(std::ostream& os, const LatencyRecorder&);
161
162} // namespace bvar
163
164#endif //BVAR_LATENCY_RECORDER_H
165