Coverage Report

Created: 2025-07-18 06:49

/src/libtorrent/src/session_stats.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
3
Copyright (c) 2014-2021, Arvid Norberg
4
Copyright (c) 2016-2017, Alden Torres
5
Copyright (c) 2019, Steven Siloti
6
Copyright (c) 2020, FranciscoPombal
7
All rights reserved.
8
9
Redistribution and use in source and binary forms, with or without
10
modification, are permitted provided that the following conditions
11
are met:
12
13
    * Redistributions of source code must retain the above copyright
14
      notice, this list of conditions and the following disclaimer.
15
    * Redistributions in binary form must reproduce the above copyright
16
      notice, this list of conditions and the following disclaimer in
17
      the documentation and/or other materials provided with the distribution.
18
    * Neither the name of the author nor the names of its
19
      contributors may be used to endorse or promote products derived
20
      from this software without specific prior written permission.
21
22
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
POSSIBILITY OF SUCH DAMAGE.
33
34
*/
35
36
#include "libtorrent/session_stats.hpp" // for stats_metric
37
#include "libtorrent/aux_/vector.hpp"
38
#include "libtorrent/performance_counters.hpp" // for counters
39
40
#include <cstring>
41
#include <algorithm>
42
43
namespace libtorrent {
44
45
#if TORRENT_ABI_VERSION == 1
46
  constexpr metric_type_t stats_metric::type_counter;
47
  constexpr metric_type_t stats_metric::type_gauge;
48
#endif
49
50
namespace {
51
52
  struct stats_metric_impl
53
  {
54
    char const* name;
55
    int value_index;
56
  };
57
58
#define METRIC(category, name) { #category "." #name, counters:: name },
59
  aux::array<stats_metric_impl, counters::num_counters> const metrics
60
  ({{
61
    // ``error_peers`` is the total number of peer disconnects
62
    // caused by an error (not initiated by this client) and
63
    // disconnected initiated by this client (``disconnected_peers``).
64
    METRIC(peer, error_peers)
65
    METRIC(peer, disconnected_peers)
66
67
    // these counters break down the peer errors into more specific
68
    // categories. These errors are what the underlying transport
69
    // reported (i.e. TCP or uTP)
70
    METRIC(peer, eof_peers)
71
    METRIC(peer, connreset_peers)
72
    METRIC(peer, connrefused_peers)
73
    METRIC(peer, connaborted_peers)
74
    METRIC(peer, notconnected_peers)
75
    METRIC(peer, perm_peers)
76
    METRIC(peer, buffer_peers)
77
    METRIC(peer, unreachable_peers)
78
    METRIC(peer, broken_pipe_peers)
79
    METRIC(peer, addrinuse_peers)
80
    METRIC(peer, no_access_peers)
81
    METRIC(peer, invalid_arg_peers)
82
    METRIC(peer, aborted_peers)
83
84
    // the total number of incoming piece requests we've received followed
85
    // by the number of rejected piece requests for various reasons.
86
    // max_piece_requests mean we already had too many outstanding requests
87
    // from this peer, so we rejected it. cancelled_piece_requests are ones
88
    // where the other end explicitly asked for the piece to be rejected.
89
    METRIC(peer, piece_requests)
90
    METRIC(peer, max_piece_requests)
91
    METRIC(peer, invalid_piece_requests)
92
    METRIC(peer, choked_piece_requests)
93
    METRIC(peer, cancelled_piece_requests)
94
    METRIC(peer, piece_rejects)
95
96
    // these counters break down the peer errors into
97
    // whether they happen on incoming or outgoing peers.
98
    METRIC(peer, error_incoming_peers)
99
    METRIC(peer, error_outgoing_peers)
100
101
    // these counters break down the peer errors into
102
    // whether they happen on encrypted peers (just
103
    // encrypted handshake) and rc4 peers (full stream
104
    // encryption). These can indicate whether encrypted
105
    // peers are more or less likely to fail
106
    METRIC(peer, error_rc4_peers)
107
    METRIC(peer, error_encrypted_peers)
108
109
    // these counters break down the peer errors into
110
    // whether they happen on uTP peers or TCP peers.
111
    // these may indicate whether one protocol is
112
    // more error prone
113
    METRIC(peer, error_tcp_peers)
114
    METRIC(peer, error_utp_peers)
115
116
    // these counters break down the reasons to
117
    // disconnect peers.
118
    METRIC(peer, connect_timeouts)
119
    METRIC(peer, uninteresting_peers)
120
    METRIC(peer, timeout_peers)
121
    METRIC(peer, no_memory_peers)
122
    METRIC(peer, too_many_peers)
123
    METRIC(peer, transport_timeout_peers)
124
    METRIC(peer, num_banned_peers)
125
    METRIC(peer, banned_for_hash_failure)
126
127
    METRIC(peer, connection_attempts)
128
    METRIC(peer, connection_attempt_loops)
129
    METRIC(peer, boost_connection_attempts)
130
    METRIC(peer, missed_connection_attempts)
131
    METRIC(peer, no_peer_connection_attempts)
132
    METRIC(peer, incoming_connections)
133
134
    // the number of peer connections for each kind of socket.
135
    // ``num_peers_half_open`` counts half-open (connecting) peers, no other
136
    // count includes those peers.
137
    // ``num_peers_up_unchoked_all`` is the total number of unchoked peers,
138
    // whereas ``num_peers_up_unchoked`` only are unchoked peers that count
139
    // against the limit (i.e. excluding peers that are unchoked because the
140
    // limit doesn't apply to them). ``num_peers_up_unchoked_optimistic`` is
141
    // the number of optimistically unchoked peers.
142
    METRIC(peer, num_tcp_peers)
143
    METRIC(peer, num_socks5_peers)
144
    METRIC(peer, num_http_proxy_peers)
145
    METRIC(peer, num_utp_peers)
146
    METRIC(peer, num_i2p_peers)
147
    METRIC(peer, num_ssl_peers)
148
    METRIC(peer, num_ssl_socks5_peers)
149
    METRIC(peer, num_ssl_http_proxy_peers)
150
    METRIC(peer, num_ssl_utp_peers)
151
152
    METRIC(peer, num_peers_half_open)
153
    METRIC(peer, num_peers_connected)
154
    METRIC(peer, num_peers_up_interested)
155
    METRIC(peer, num_peers_down_interested)
156
    METRIC(peer, num_peers_up_unchoked_all)
157
    METRIC(peer, num_peers_up_unchoked_optimistic)
158
    METRIC(peer, num_peers_up_unchoked)
159
    METRIC(peer, num_peers_down_unchoked)
160
    METRIC(peer, num_peers_up_requests)
161
    METRIC(peer, num_peers_down_requests)
162
    METRIC(peer, num_peers_end_game)
163
    METRIC(peer, num_peers_up_disk)
164
    METRIC(peer, num_peers_down_disk)
165
166
    // These counters count the number of times the
167
    // network thread wakes up for each respective
168
    // reason. If these counters are very large, it
169
    // may indicate a performance issue, causing the
170
    // network thread to wake up too ofte, wasting CPU.
171
    // mitigate it by increasing buffers and limits
172
    // for the specific trigger that wakes up the
173
    // thread.
174
    METRIC(net, on_read_counter)
175
    METRIC(net, on_write_counter)
176
    METRIC(net, on_tick_counter)
177
    METRIC(net, on_lsd_counter)
178
    METRIC(net, on_lsd_peer_counter)
179
    METRIC(net, on_udp_counter)
180
    METRIC(net, on_accept_counter)
181
    METRIC(net, on_disk_queue_counter)
182
    METRIC(net, on_disk_counter)
183
184
    // total number of bytes sent and received by the session
185
    METRIC(net, sent_payload_bytes)
186
    METRIC(net, sent_bytes)
187
    METRIC(net, sent_ip_overhead_bytes)
188
    METRIC(net, sent_tracker_bytes)
189
    METRIC(net, recv_payload_bytes)
190
    METRIC(net, recv_bytes)
191
    METRIC(net, recv_ip_overhead_bytes)
192
    METRIC(net, recv_tracker_bytes)
193
194
    // the number of sockets currently waiting for upload and download
195
    // bandwidth from the rate limiter.
196
    METRIC(net, limiter_up_queue)
197
    METRIC(net, limiter_down_queue)
198
199
    // the number of upload and download bytes waiting to be handed out from
200
    // the rate limiter.
201
    METRIC(net, limiter_up_bytes)
202
    METRIC(net, limiter_down_bytes)
203
204
    // the number of bytes downloaded that had to be discarded because they
205
    // failed the hash check
206
    METRIC(net, recv_failed_bytes)
207
208
    // the number of downloaded bytes that were discarded because they
209
    // were downloaded multiple times (from different peers)
210
    METRIC(net, recv_redundant_bytes)
211
212
    // is false by default and set to true when
213
    // the first incoming connection is established
214
    // this is used to know if the client is behind
215
    // NAT or not.
216
    METRIC(net, has_incoming_connections)
217
218
    // these gauges count the number of torrents in
219
    // different states. Each torrent only belongs to
220
    // one of these states. For torrents that could
221
    // belong to multiple of these, the most prominent
222
    // in picked. For instance, a torrent with an error
223
    // counts as an error-torrent, regardless of its other
224
    // state.
225
    METRIC(ses, num_checking_torrents)
226
    METRIC(ses, num_stopped_torrents)
227
    METRIC(ses, num_upload_only_torrents)
228
    METRIC(ses, num_downloading_torrents)
229
    METRIC(ses, num_seeding_torrents)
230
    METRIC(ses, num_queued_seeding_torrents)
231
    METRIC(ses, num_queued_download_torrents)
232
    METRIC(ses, num_error_torrents)
233
234
    // the number of torrents that don't have the
235
    // IP filter applied to them.
236
    METRIC(ses, non_filter_torrents)
237
238
    // these count the number of times a piece has passed the
239
    // hash check, the number of times a piece was successfully
240
    // written to disk and the number of total possible pieces
241
    // added by adding torrents. e.g. when adding a torrent with
242
    // 1000 piece, num_total_pieces_added is incremented by 1000.
243
    METRIC(ses, num_piece_passed)
244
    METRIC(ses, num_piece_failed)
245
246
    METRIC(ses, num_have_pieces)
247
    METRIC(ses, num_total_pieces_added)
248
249
    // the number of allowed unchoked peers
250
    METRIC(ses, num_unchoke_slots)
251
252
    // the number of listen sockets that are currently accepting incoming
253
    // connections
254
    METRIC(ses, num_outstanding_accept)
255
256
    // bittorrent message counters. These counters are incremented
257
    // every time a message of the corresponding type is received from
258
    // or sent to a bittorrent peer.
259
    METRIC(ses, num_incoming_choke)
260
    METRIC(ses, num_incoming_unchoke)
261
    METRIC(ses, num_incoming_interested)
262
    METRIC(ses, num_incoming_not_interested)
263
    METRIC(ses, num_incoming_have)
264
    METRIC(ses, num_incoming_bitfield)
265
    METRIC(ses, num_incoming_request)
266
    METRIC(ses, num_incoming_piece)
267
    METRIC(ses, num_incoming_cancel)
268
    METRIC(ses, num_incoming_dht_port)
269
    METRIC(ses, num_incoming_suggest)
270
    METRIC(ses, num_incoming_have_all)
271
    METRIC(ses, num_incoming_have_none)
272
    METRIC(ses, num_incoming_reject)
273
    METRIC(ses, num_incoming_allowed_fast)
274
    METRIC(ses, num_incoming_ext_handshake)
275
    METRIC(ses, num_incoming_pex)
276
    METRIC(ses, num_incoming_metadata)
277
    METRIC(ses, num_incoming_extended)
278
279
    METRIC(ses, num_outgoing_choke)
280
    METRIC(ses, num_outgoing_unchoke)
281
    METRIC(ses, num_outgoing_interested)
282
    METRIC(ses, num_outgoing_not_interested)
283
    METRIC(ses, num_outgoing_have)
284
    METRIC(ses, num_outgoing_bitfield)
285
    METRIC(ses, num_outgoing_request)
286
    METRIC(ses, num_outgoing_piece)
287
    METRIC(ses, num_outgoing_cancel)
288
    METRIC(ses, num_outgoing_dht_port)
289
    METRIC(ses, num_outgoing_suggest)
290
    METRIC(ses, num_outgoing_have_all)
291
    METRIC(ses, num_outgoing_have_none)
292
    METRIC(ses, num_outgoing_reject)
293
    METRIC(ses, num_outgoing_allowed_fast)
294
    METRIC(ses, num_outgoing_ext_handshake)
295
    METRIC(ses, num_outgoing_pex)
296
    METRIC(ses, num_outgoing_metadata)
297
    METRIC(ses, num_outgoing_extended)
298
    METRIC(ses, num_outgoing_hash_request)
299
    METRIC(ses, num_outgoing_hashes)
300
    METRIC(ses, num_outgoing_hash_reject)
301
302
    // the number of wasted downloaded bytes by reason of the bytes being
303
    // wasted.
304
    METRIC(ses, waste_piece_timed_out)
305
    METRIC(ses, waste_piece_cancelled)
306
    METRIC(ses, waste_piece_unknown)
307
    METRIC(ses, waste_piece_seed)
308
    METRIC(ses, waste_piece_end_game)
309
    METRIC(ses, waste_piece_closing)
310
311
    // the number of pieces considered while picking pieces
312
    METRIC(picker, piece_picker_partial_loops)
313
    METRIC(picker, piece_picker_suggest_loops)
314
    METRIC(picker, piece_picker_sequential_loops)
315
    METRIC(picker, piece_picker_reverse_rare_loops)
316
    METRIC(picker, piece_picker_rare_loops)
317
    METRIC(picker, piece_picker_rand_start_loops)
318
    METRIC(picker, piece_picker_rand_loops)
319
    METRIC(picker, piece_picker_busy_loops)
320
321
    // This breaks down the piece picks into the event that
322
    // triggered it
323
    METRIC(picker, reject_piece_picks)
324
    METRIC(picker, unchoke_piece_picks)
325
    METRIC(picker, incoming_redundant_piece_picks)
326
    METRIC(picker, incoming_piece_picks)
327
    METRIC(picker, end_game_piece_picks)
328
    METRIC(picker, snubbed_piece_picks)
329
    METRIC(picker, interesting_piece_picks)
330
    METRIC(picker, hash_fail_piece_picks)
331
332
    // the number of microseconds it takes from receiving a request from a
333
    // peer until we're sending the response back on the socket.
334
    METRIC(disk, request_latency)
335
336
    METRIC(disk, disk_blocks_in_use)
337
338
    // ``queued_disk_jobs`` is the number of disk jobs currently queued,
339
    // waiting to be executed by a disk thread.
340
    METRIC(disk, queued_disk_jobs)
341
    METRIC(disk, num_running_disk_jobs)
342
    METRIC(disk, num_read_jobs)
343
    METRIC(disk, num_write_jobs)
344
    METRIC(disk, num_jobs)
345
    METRIC(disk, blocked_disk_jobs)
346
347
    METRIC(disk, num_writing_threads)
348
    METRIC(disk, num_running_threads)
349
350
    // the number of bytes we have sent to the disk I/O
351
    // thread for writing. Every time we hear back from
352
    // the disk I/O thread with a completed write job, this
353
    // is updated to the number of bytes the disk I/O thread
354
    // is actually waiting for to be written (as opposed to
355
    // bytes just hanging out in the cache)
356
    METRIC(disk, queued_write_bytes)
357
358
    // the number of blocks written and read from disk in total. A block is 16
359
    // kiB. ``num_blocks_written`` and ``num_blocks_read``
360
    METRIC(disk, num_blocks_written)
361
    METRIC(disk, num_blocks_read)
362
363
    // the total number of blocks run through SHA-1 hashing
364
    METRIC(disk, num_blocks_hashed)
365
366
    // the number of disk I/O operation for reads and writes. One disk
367
    // operation may transfer more then one block.
368
    METRIC(disk, num_write_ops)
369
    METRIC(disk, num_read_ops)
370
371
    // the number of blocks that had to be read back from disk in order to
372
    // hash a piece (when verifying against the piece hash)
373
    METRIC(disk, num_read_back)
374
375
    // cumulative time spent in various disk jobs, as well
376
    // as total for all disk jobs. Measured in microseconds
377
    METRIC(disk, disk_read_time)
378
    METRIC(disk, disk_write_time)
379
    METRIC(disk, disk_hash_time)
380
    METRIC(disk, disk_job_time)
381
382
    // for each kind of disk job, a counter of how many jobs of that kind
383
    // are currently blocked by a disk fence
384
    METRIC(disk, num_fenced_read)
385
    METRIC(disk, num_fenced_write)
386
    METRIC(disk, num_fenced_hash)
387
    METRIC(disk, num_fenced_move_storage)
388
    METRIC(disk, num_fenced_release_files)
389
    METRIC(disk, num_fenced_delete_files)
390
    METRIC(disk, num_fenced_check_fastresume)
391
    METRIC(disk, num_fenced_save_resume_data)
392
    METRIC(disk, num_fenced_rename_file)
393
    METRIC(disk, num_fenced_stop_torrent)
394
    METRIC(disk, num_fenced_flush_piece)
395
    METRIC(disk, num_fenced_flush_hashed)
396
    METRIC(disk, num_fenced_flush_storage)
397
    METRIC(disk, num_fenced_file_priority)
398
    METRIC(disk, num_fenced_load_torrent)
399
    METRIC(disk, num_fenced_clear_piece)
400
    METRIC(disk, num_fenced_tick_storage)
401
402
    // The number of nodes in the DHT routing table
403
    METRIC(dht, dht_nodes)
404
405
    // The number of replacement nodes in the DHT routing table
406
    METRIC(dht, dht_node_cache)
407
408
    // the number of torrents currently tracked by our DHT node
409
    METRIC(dht, dht_torrents)
410
411
    // the number of peers currently tracked by our DHT node
412
    METRIC(dht, dht_peers)
413
414
    // the number of immutable data items tracked by our DHT node
415
    METRIC(dht, dht_immutable_data)
416
417
    // the number of mutable data items tracked by our DHT node
418
    METRIC(dht, dht_mutable_data)
419
420
    // the number of RPC observers currently allocated
421
    METRIC(dht, dht_allocated_observers)
422
423
    // the total number of DHT messages sent and received
424
    METRIC(dht, dht_messages_in)
425
    METRIC(dht, dht_messages_out)
426
427
    // the number of incoming DHT requests that were dropped. There are a few
428
    // different reasons why incoming DHT packets may be dropped:
429
    //
430
    // 1. there wasn't enough send quota to respond to them.
431
    // 2. the Denial of service logic kicked in, blocking the peer
432
    // 3. ignore_dark_internet is enabled, and the packet came from a
433
    //    non-public IP address
434
    // 4. the bencoding of the message was invalid
435
    METRIC(dht, dht_messages_in_dropped)
436
437
    // the number of outgoing messages that failed to be
438
    // sent
439
    METRIC(dht, dht_messages_out_dropped)
440
441
    // the total number of bytes sent and received by the DHT
442
    METRIC(dht, dht_bytes_in)
443
    METRIC(dht, dht_bytes_out)
444
445
    // the number of DHT messages we've sent and received
446
    // by kind.
447
    METRIC(dht, dht_ping_in)
448
    METRIC(dht, dht_ping_out)
449
    METRIC(dht, dht_find_node_in)
450
    METRIC(dht, dht_find_node_out)
451
    METRIC(dht, dht_get_peers_in)
452
    METRIC(dht, dht_get_peers_out)
453
    METRIC(dht, dht_announce_peer_in)
454
    METRIC(dht, dht_announce_peer_out)
455
    METRIC(dht, dht_get_in)
456
    METRIC(dht, dht_get_out)
457
    METRIC(dht, dht_put_in)
458
    METRIC(dht, dht_put_out)
459
    METRIC(dht, dht_sample_infohashes_in)
460
    METRIC(dht, dht_sample_infohashes_out)
461
462
    // the number of failed incoming DHT requests by kind of request
463
    METRIC(dht, dht_invalid_announce)
464
    METRIC(dht, dht_invalid_get_peers)
465
    METRIC(dht, dht_invalid_find_node)
466
    METRIC(dht, dht_invalid_put)
467
    METRIC(dht, dht_invalid_get)
468
    METRIC(dht, dht_invalid_sample_infohashes)
469
470
    // The number of times a lost packet has been interpreted as congestion,
471
    // cutting the congestion window in half. Some lost packets are not
472
    // interpreted as congestion, notably MTU-probes
473
    METRIC(utp, utp_packet_loss)
474
475
    // The number of timeouts experienced. This is when a connection doesn't
476
    // hear back from the other end within a sliding average RTT + 2 average
477
    // deviations from the mean (approximately). The actual time out is
478
    // configurable and also depends on the state of the socket.
479
    METRIC(utp, utp_timeout)
480
481
    // The total number of packets sent and received
482
    METRIC(utp, utp_packets_in)
483
    METRIC(utp, utp_packets_out)
484
485
    // The number of packets lost but re-sent by the fast-retransmit logic.
486
    // This logic is triggered after 3 duplicate ACKs.
487
    METRIC(utp, utp_fast_retransmit)
488
489
    // The number of packets that were re-sent, for whatever reason
490
    METRIC(utp, utp_packet_resend)
491
492
    // The number of incoming packets where the delay samples were above
493
    // and below the delay target, respectively. The delay target is
494
    // configurable and is a parameter to the LEDBAT congestion control.
495
    METRIC(utp, utp_samples_above_target)
496
    METRIC(utp, utp_samples_below_target)
497
498
    // The total number of packets carrying payload received and sent,
499
    // respectively.
500
    METRIC(utp, utp_payload_pkts_in)
501
    METRIC(utp, utp_payload_pkts_out)
502
503
    // The number of packets received that are not valid uTP packets (but
504
    // were sufficiently similar to not be treated as DHT or UDP tracker
505
    // packets).
506
    METRIC(utp, utp_invalid_pkts_in)
507
508
    // The number of duplicate payload packets received. This may happen if
509
    // the outgoing ACK is lost.
510
    METRIC(utp, utp_redundant_pkts_in)
511
512
    // the number of uTP sockets in each respective state
513
    METRIC(utp, num_utp_idle)
514
    METRIC(utp, num_utp_syn_sent)
515
    METRIC(utp, num_utp_connected)
516
    METRIC(utp, num_utp_fin_sent)
517
    METRIC(utp, num_utp_close_wait)
518
    METRIC(utp, num_utp_deleted)
519
520
    // the buffer sizes accepted by
521
    // socket send and receive calls respectively.
522
    // The larger the buffers are, the more efficient,
523
    // because it require fewer system calls per byte.
524
    // The size is 1 << n, where n is the number
525
    // at the end of the counter name. i.e.
526
    // 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192,
527
    // 16384, 32768, 65536, 131072, 262144, 524288, 1048576
528
    // bytes
529
    METRIC(sock_bufs, socket_send_size3)
530
    METRIC(sock_bufs, socket_send_size4)
531
    METRIC(sock_bufs, socket_send_size5)
532
    METRIC(sock_bufs, socket_send_size6)
533
    METRIC(sock_bufs, socket_send_size7)
534
    METRIC(sock_bufs, socket_send_size8)
535
    METRIC(sock_bufs, socket_send_size9)
536
    METRIC(sock_bufs, socket_send_size10)
537
    METRIC(sock_bufs, socket_send_size11)
538
    METRIC(sock_bufs, socket_send_size12)
539
    METRIC(sock_bufs, socket_send_size13)
540
    METRIC(sock_bufs, socket_send_size14)
541
    METRIC(sock_bufs, socket_send_size15)
542
    METRIC(sock_bufs, socket_send_size16)
543
    METRIC(sock_bufs, socket_send_size17)
544
    METRIC(sock_bufs, socket_send_size18)
545
    METRIC(sock_bufs, socket_send_size19)
546
    METRIC(sock_bufs, socket_send_size20)
547
    METRIC(sock_bufs, socket_recv_size3)
548
    METRIC(sock_bufs, socket_recv_size4)
549
    METRIC(sock_bufs, socket_recv_size5)
550
    METRIC(sock_bufs, socket_recv_size6)
551
    METRIC(sock_bufs, socket_recv_size7)
552
    METRIC(sock_bufs, socket_recv_size8)
553
    METRIC(sock_bufs, socket_recv_size9)
554
    METRIC(sock_bufs, socket_recv_size10)
555
    METRIC(sock_bufs, socket_recv_size11)
556
    METRIC(sock_bufs, socket_recv_size12)
557
    METRIC(sock_bufs, socket_recv_size13)
558
    METRIC(sock_bufs, socket_recv_size14)
559
    METRIC(sock_bufs, socket_recv_size15)
560
    METRIC(sock_bufs, socket_recv_size16)
561
    METRIC(sock_bufs, socket_recv_size17)
562
    METRIC(sock_bufs, socket_recv_size18)
563
    METRIC(sock_bufs, socket_recv_size19)
564
    METRIC(sock_bufs, socket_recv_size20)
565
566
    // if the outstanding tracker announce limit is reached, tracker
567
    // announces are queued, to be issued when an announce slot opens up.
568
    // this measure the number of tracker announces currently in the
569
    // queue
570
    METRIC(tracker, num_queued_tracker_announces)
571
    // ... more
572
  }});
573
#undef METRIC
574
  } // anonymous namespace
575
576
  std::vector<stats_metric> session_stats_metrics()
577
0
  {
578
0
    aux::vector<stats_metric> stats;
579
0
    stats.resize(metrics.size());
580
0
    for (int i = 0; i < metrics.end_index(); ++i)
581
0
    {
582
0
      stats[i].name = metrics[i].name;
583
0
      stats[i].value_index = metrics[i].value_index;
584
0
      stats[i].type = metrics[i].value_index >= counters::num_stats_counters
585
0
        ? metric_type_t::gauge : metric_type_t::counter;
586
0
    }
587
0
    return TORRENT_RVO(stats);
588
0
  }
589
590
  int find_metric_idx(string_view name)
591
0
  {
592
0
    auto const i = std::find_if(std::begin(metrics), std::end(metrics)
593
0
      , [name](stats_metric_impl const& metr)
594
0
      { return metr.name == name; });
595
596
0
    if (i == std::end(metrics)) return -1;
597
0
    return i->value_index;
598
0
  }
599
}