Flow-IPC 3.0.0
Flow-IPC project: Full implementation reference.
channel_stats.hpp
Go to the documentation of this file.
1/* Flow-IPC: Structured Transport
2 * Copyright (c) 2023 Akamai Technologies, Inc.; and other contributors.
3 * Each commit is copyright by its respective author or author's employer.
4 *
5 * Licensed under the MIT License:
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE. */
24
25/// @file
26#pragma once
27
29#include <flow/util/stat/histo.hpp>
30#include <flow/util/stat/stat_set.hpp>
31#include <cstdint>
32#include <string>
33
35{
36
37// Types.
38
39/**
40 * Stats specific to Channel::sync_request() -- the blocking synchronous request-response API
41 * available only via struc::Channel (not struc::sync_io::Channel). Composed into Channel_stats
42 * (as Channel_stats::m_sync_req) but is also a standalone Stat_set in its own right.
43 *
44 * @internal
45 * It is updated, but more saliently reset via `flow::util::stat::stats_reset()`, on its own by
46 * struc::Channel internals. Then when the user accesses struc::Channel::stats(), the two parts are
47 * put together into struc::stat::Channel_stats.
48 */
50{
51 // Data.
52
53 /**
54 * Total valid Channel::sync_request() invocations. "Valid" means this discounts those calls that return
55 * null without emitting an error (called on on already-hosed channel/similar).
56 *
57 * @note It does include the situation where `sync_request()` immediately fails, thus hosing the `Channel`
58 * and emitting error. This is a small caveat unlikely to be of much import, as such a thing can
59 * happen at most once.
60 */
61 uint64_t m_count = 0;
62
63 /**
64 * Channel::sync_request() real-time latency histogram: time period from initiating non-blocking send
65 * to return (whether success, timeout, or error), in microseconds. If it counts in #m_count, it is recorded
66 * here, and vice versa. A late-arriving response (#m_late_responses) is recorded as ending when the timeout
67 * occurs (not when it arrives past the timeout).
68 *
69 * Default buckets: same config as sync_io::stat::Channel_stats::Rcv::m_histo_one_off_request_rtt_usec
70 * (see its doc header for rationale) -- after all a `sync_request()` latency *is* a one-off-request RTT:
71 * sync_request() internally layers a blocking wait atop a one-off `async_request()`.
72 *
73 * @note User can override bucket config via
74 * Channel::stats_configure_sync_req_latency_histogram() before Channel::start().
75 */
76 flow::util::stat::Histogram_counter m_histo_latency_usec
79
80 /**
81 * Channel::sync_request() invocations (counted in #m_count) that returned
82 * transport::error::Code::S_TIMEOUT.
83 */
84 uint64_t m_timeouts = 0;
85
86 /**
87 * Count of the event wherein response arrived after Channel::sync_request() had already timed out; the
88 * response was dropped.
89 *
90 * High #m_late_responses relative to #m_timeouts indicates that the opposing process *is*
91 * responding but too slowly -- a different diagnosis than "never responded."
92 *
93 * @note A thing that increments #m_late_responses also increments #m_timeouts (but not necessarily vice versa).
94 */
95 uint64_t m_late_responses = 0;
96}; // struct Channel_sync_req_stats
97
98/**
99 * Cumulative stats from a struc::Channel, composing the underlying sync_io::stat::Channel_stats
100 * with `struc::Channel`-specific stats including vis-a-vis Channel::sync_request(). #m_core contains
101 * the former; #m_sync_req contains the latter (a Channel_sync_req_stats peer).
102 *
103 * A struc::Channel user obtains this via Channel::stats(); a sync_io::Channel user obtains
104 * sync_io::stat::Channel_stats via that class's own sync_io::Channel::stats() instead.
105 *
106 * @see doc header for struc::Channel::stats().
107 * @see doc header for #m_core; there are certain subtleties that may be of interest.
108 */
110{
111 // Data.
112
113 /**
114 * Stats from the underlying sync_io::Channel.
115 *
116 * @note While the vast majority of Channel methods are mirrored in sync_io::Channel, and vice versa,
117 * one exception is that Channel::async_request() will invoke sync_io::Channel::async_request() --
118 * but so will Channel::sync_request(). Therefore there may be counts/gauges in sync_io::stat::Channel_stats
119 * (with respect to requests generally) that one might not naively expect to be as high as observed,
120 * here in #m_core.
121 */
123
124 /// Stats specific to Channel::sync_request().
126}; // struct Channel_stats
127
128// Template implementations.
129
130template<typename Visitor>
131void declare_stats(const flow::util::stat::Stat_name& name_prefix,
132 const Channel_sync_req_stats* src_stats, Channel_sync_req_stats* target_stats,
133 Visitor&& visitor)
134{
135 FLOW_UTIL_STAT_DECLARE(m_count, ACCUMULATOR);
136 FLOW_UTIL_STAT_DECLARE(m_histo_latency_usec, ACCUMULATOR);
137 FLOW_UTIL_STAT_DECLARE(m_timeouts, ACCUMULATOR);
138 FLOW_UTIL_STAT_DECLARE(m_late_responses, ACCUMULATOR);
139} // declare_stats(Channel_sync_req_stats)
140
141template<typename Visitor>
142void declare_stats(const flow::util::stat::Stat_name& name_prefix,
143 const Channel_stats* src_stats, Channel_stats* target_stats,
144 Visitor&& visitor)
145{
146 /* Core stats -- delegate to sync_io::stat's declare_stats() (found via ADL on sync_io::stat::Channel_stats).
147 * The sync_io stats keep `name_prefix` unchanged (no "core." prefix added): they are meaningful in their own
148 * right, and the context/separation should be quite clear visually. */
150 src_stats ? &src_stats->m_core : nullptr,
151 target_stats ? &target_stats->m_core : nullptr,
152 visitor);
153
154 /* m_sync_req: also delegate (it is reset standalone via Channel::stats_reset()).
155 * Add "sync_req." sub-prefix; as of this writing without the "sync_req." context these stats look rather
156 * ambiguous at a glance; for example `count=[4]`: that is count of sync_request()s. Hopefully you feel
157 * the distinction between that and hypothetically adding `core.` (or whatever) above. */
158 declare_stats(flow::util::stat::Stat_name{name_prefix, "sync_req."},
159 src_stats ? &src_stats->m_sync_req : nullptr,
160 target_stats ? &target_stats->m_sync_req : nullptr,
161 visitor);
162} // declare_stats(Channel_stats)
163
164} // namespace ipc::transport::struc::stat
Stats-related sub-namespace, for ADL segregation and general organization.
void declare_stats(const flow::util::stat::Stat_name &name_prefix, const Channel_sync_req_stats *src_stats, Channel_sync_req_stats *target_stats, Visitor &&visitor)
Declares the stats for Channel_sync_req_stats.
void declare_stats(const flow::util::stat::Stat_name &name_prefix, const Channel_stats *src_stats, Channel_stats *target_stats, Visitor &&visitor)
Declares the stats for Channel_stats.
Cumulative stats from a struc::Channel, composing the underlying sync_io::stat::Channel_stats with st...
sync_io::stat::Channel_stats m_core
Stats from the underlying sync_io::Channel.
Channel_sync_req_stats m_sync_req
Stats specific to Channel::sync_request().
Stats specific to Channel::sync_request() – the blocking synchronous request-response API available o...
flow::util::stat::Histogram_counter m_histo_latency_usec
Channel::sync_request() real-time latency histogram: time period from initiating non-blocking send to...
uint64_t m_timeouts
Channel::sync_request() invocations (counted in m_count) that returned transport::error::Code::S_TIME...
uint64_t m_count
Total valid Channel::sync_request() invocations.
uint64_t m_late_responses
Count of the event wherein response arrived after Channel::sync_request() had already timed out; the ...
static constexpr flow::util::stat::Histogram_counter::value_t S_HISTO_RTT_BUCKET_N_SZ_USEC
Last-bucket width for m_histo_one_off_request_rtt_usec (default config); values past it land in that ...
static const std::vector< flow::util::stat::Histogram_counter::value_t > S_HISTO_RTT_BUCKET_VAL0S_USEC
Bucket min-values for m_histo_one_off_request_rtt_usec (default config): a log-scale-ish 1-2-5 ladder...
Cumulative stats from a struc::sync_io::Channel, covering both send and receive directions as well as...