blob: f940018ff28f4ed9c9780865ee952a7d42b1547c [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*
Harald Welte3b007f82022-04-18 11:39:08 +02002 * (C) 2009-2022 by Harald Welte <laforge@gnumonks.org>
Jacob Erlbeck45513e62015-10-19 15:14:13 +02003 * (C) 2009-2014 by Holger Hans Peter Freyther
Harald Weltee08da972017-11-13 01:00:26 +09004 * (C) 2015 by sysmocom - s.f.m.c. GmbH
Jacob Erlbeck45513e62015-10-19 15:14:13 +02005 * All Rights Reserved
6 *
Harald Weltee08da972017-11-13 01:00:26 +09007 * SPDX-License-Identifier: GPL-2.0+
8 *
Jacob Erlbeck45513e62015-10-19 15:14:13 +02009 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
Jacob Erlbeck45513e62015-10-19 15:14:13 +020019 */
20
21#include <stdlib.h>
22#include <string.h>
23
Pau Espin Pedrol88955fb2023-01-18 18:54:00 +010024#include "config.h"
Jacob Erlbeck45513e62015-10-19 15:14:13 +020025
26#include <osmocom/vty/command.h>
27#include <osmocom/vty/buffer.h>
28#include <osmocom/vty/vty.h>
29#include <osmocom/vty/telnet_interface.h>
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020030#include <osmocom/vty/telnet_interface.h>
Jacob Erlbeck45513e62015-10-19 15:14:13 +020031#include <osmocom/vty/misc.h>
32
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020033#include <osmocom/core/stats.h>
Harald Welte216338c2017-10-15 19:46:19 +020034#include <osmocom/core/counter.h>
Alexander Couzensad580ba2016-05-16 16:01:45 +020035#include <osmocom/core/rate_ctr.h>
Philipp Maierb1ef8f52021-12-06 16:31:02 +010036#include <osmocom/core/stats_tcp.h>
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020037
Jacob Erlbeck45513e62015-10-19 15:14:13 +020038#define CFG_STATS_STR "Configure stats sub-system\n"
39#define CFG_REPORTER_STR "Configure a stats reporter\n"
40
41#define SHOW_STATS_STR "Show statistical values\n"
Harald Welte3b007f82022-04-18 11:39:08 +020042#define SKIP_ZERO_STR "Skip items with total count zero\n"
Jacob Erlbeck45513e62015-10-19 15:14:13 +020043
Daniel Willmann1a1de332020-07-14 18:11:14 +020044#define STATS_STR "Stats related commands\n"
45
Harald Welte8c648252017-10-16 15:17:03 +020046/*! \file stats_vty.c
Neels Hofmeyr87e45502017-06-20 00:17:59 +020047 * VTY interface for statsd / statistic items
Harald Welte8c648252017-10-16 15:17:03 +020048 *
49 * This code allows you to register a couple of VTY commands that
50 * permit configuration of the \ref stats functionality from the VTY.
51 *
52 * Use \ref osmo_stats_vty_add_cmds once at application start-up to
53 * enable related commands.
Harald Welte96e2a002017-06-12 21:44:18 +020054 */
55
Alexander Couzense052dc22016-10-04 18:04:37 +020056/* containing version info */
57extern struct host host;
58
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020059struct cmd_node cfg_stats_node = {
60 CFG_STATS_NODE,
61 "%s(config-stats)# ",
62 1
63};
64
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +010065static const struct value_string stats_class_strs[] = {
66 { OSMO_STATS_CLASS_GLOBAL, "global" },
67 { OSMO_STATS_CLASS_PEER, "peer" },
68 { OSMO_STATS_CLASS_SUBSCRIBER, "subscriber" },
69 { 0, NULL }
70};
71
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +010072static struct osmo_stats_reporter *osmo_stats_vty2srep(struct vty *vty)
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020073{
74 if (vty->node == CFG_STATS_NODE)
75 return vty->index;
76
77 return NULL;
78}
79
80static int set_srep_parameter_str(struct vty *vty,
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +010081 int (*fun)(struct osmo_stats_reporter *, const char *),
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020082 const char *val, const char *param_name)
83{
84 int rc;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +010085 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020086 OSMO_ASSERT(srep);
87
88 rc = fun(srep, val);
89 if (rc < 0) {
90 vty_out(vty, "%% Unable to set %s: %s%s",
91 param_name, strerror(-rc), VTY_NEWLINE);
92 return CMD_WARNING;
93 }
94
95 return CMD_SUCCESS;
96}
97
98static int set_srep_parameter_int(struct vty *vty,
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +010099 int (*fun)(struct osmo_stats_reporter *, int),
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200100 const char *val, const char *param_name)
101{
102 int rc;
103 int int_val;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100104 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200105 OSMO_ASSERT(srep);
106
107 int_val = atoi(val);
108
109 rc = fun(srep, int_val);
110 if (rc < 0) {
111 vty_out(vty, "%% Unable to set %s: %s%s",
112 param_name, strerror(-rc), VTY_NEWLINE);
113 return CMD_WARNING;
114 }
115
116 return CMD_SUCCESS;
117}
118
119DEFUN(cfg_stats_reporter_local_ip, cfg_stats_reporter_local_ip_cmd,
120 "local-ip ADDR",
121 "Set the IP address to which we bind locally\n"
122 "IP Address\n")
123{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100124 return set_srep_parameter_str(vty, osmo_stats_reporter_set_local_addr,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200125 argv[0], "local address");
126}
127
128DEFUN(cfg_no_stats_reporter_local_ip, cfg_no_stats_reporter_local_ip_cmd,
129 "no local-ip",
130 NO_STR
131 "Set the IP address to which we bind locally\n")
132{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100133 return set_srep_parameter_str(vty, osmo_stats_reporter_set_local_addr,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200134 NULL, "local address");
135}
136
137DEFUN(cfg_stats_reporter_remote_ip, cfg_stats_reporter_remote_ip_cmd,
138 "remote-ip ADDR",
139 "Set the remote IP address to which we connect\n"
140 "IP Address\n")
141{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100142 return set_srep_parameter_str(vty, osmo_stats_reporter_set_remote_addr,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200143 argv[0], "remote address");
144}
145
146DEFUN(cfg_stats_reporter_remote_port, cfg_stats_reporter_remote_port_cmd,
147 "remote-port <1-65535>",
148 "Set the remote port to which we connect\n"
149 "Remote port number\n")
150{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100151 return set_srep_parameter_int(vty, osmo_stats_reporter_set_remote_port,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200152 argv[0], "remote port");
153}
154
Jacob Erlbeckd01acfc2015-10-26 16:22:45 +0100155DEFUN(cfg_stats_reporter_mtu, cfg_stats_reporter_mtu_cmd,
156 "mtu <100-65535>",
157 "Set the maximum packet size\n"
158 "Size in byte\n")
159{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100160 return set_srep_parameter_int(vty, osmo_stats_reporter_set_mtu,
Jacob Erlbeckd01acfc2015-10-26 16:22:45 +0100161 argv[0], "mtu");
162}
163
164DEFUN(cfg_no_stats_reporter_mtu, cfg_no_stats_reporter_mtu_cmd,
165 "no mtu",
166 NO_STR "Set the maximum packet size\n")
167{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100168 return set_srep_parameter_int(vty, osmo_stats_reporter_set_mtu,
Holger Hans Peter Freyther8f0374f2015-11-02 15:53:09 +0100169 "0", "mtu");
Jacob Erlbeckd01acfc2015-10-26 16:22:45 +0100170}
171
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200172DEFUN(cfg_stats_reporter_prefix, cfg_stats_reporter_prefix_cmd,
173 "prefix PREFIX",
174 "Set the item name prefix\n"
175 "The prefix string\n")
176{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100177 return set_srep_parameter_str(vty, osmo_stats_reporter_set_name_prefix,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200178 argv[0], "prefix string");
179}
180
181DEFUN(cfg_no_stats_reporter_prefix, cfg_no_stats_reporter_prefix_cmd,
182 "no prefix",
183 NO_STR
184 "Set the item name prefix\n")
185{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100186 return set_srep_parameter_str(vty, osmo_stats_reporter_set_name_prefix,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200187 "", "prefix string");
188}
189
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100190DEFUN(cfg_stats_reporter_level, cfg_stats_reporter_level_cmd,
191 "level (global|peer|subscriber)",
192 "Set the maximum group level\n"
193 "Report global groups only\n"
194 "Report global and network peer related groups\n"
195 "Report global, peer, and subscriber groups\n")
196{
197 int level = get_string_value(stats_class_strs, argv[0]);
198 int rc;
199 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
200
201 OSMO_ASSERT(srep);
202 rc = osmo_stats_reporter_set_max_class(srep, level);
203 if (rc < 0) {
204 vty_out(vty, "%% Unable to set level: %s%s",
205 strerror(-rc), VTY_NEWLINE);
206 return CMD_WARNING;
207 }
208
209 return 0;
210}
211
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200212DEFUN(cfg_stats_reporter_enable, cfg_stats_reporter_enable_cmd,
213 "enable",
214 "Enable the reporter\n")
215{
216 int rc;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100217 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200218 OSMO_ASSERT(srep);
219
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100220 rc = osmo_stats_reporter_enable(srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200221 if (rc < 0) {
222 vty_out(vty, "%% Unable to enable the reporter: %s%s",
223 strerror(-rc), VTY_NEWLINE);
224 return CMD_WARNING;
225 }
226
227 return CMD_SUCCESS;
228}
229
230DEFUN(cfg_stats_reporter_disable, cfg_stats_reporter_disable_cmd,
231 "disable",
232 "Disable the reporter\n")
233{
234 int rc;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100235 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200236 OSMO_ASSERT(srep);
237
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100238 rc = osmo_stats_reporter_disable(srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200239 if (rc < 0) {
240 vty_out(vty, "%% Unable to disable the reporter: %s%s",
241 strerror(-rc), VTY_NEWLINE);
242 return CMD_WARNING;
243 }
244
245 return CMD_SUCCESS;
246}
247
Alexander Chemerisdfebf402020-05-08 19:10:40 +0300248DEFUN(cfg_stats_reporter_flush_period, cfg_stats_reporter_flush_period_cmd,
249 "flush-period <0-65535>",
250 CFG_STATS_STR "Send all stats even if they have not changed (i.e. force the flush)"
251 "every N-th reporting interval. Set to 0 to disable regular flush (default).\n"
252 "0 to disable regular flush (default), 1 to flush every time, 2 to flush every 2nd time, etc\n")
253{
254 int rc;
255 unsigned int period = atoi(argv[0]);
256 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
257 OSMO_ASSERT(srep);
258
259 rc = osmo_stats_reporter_set_flush_period(srep, period);
260 if (rc < 0) {
261 vty_out(vty, "%% Unable to set force flush period: %s%s",
262 strerror(-rc), VTY_NEWLINE);
263 return CMD_WARNING;
264 }
265
266 return CMD_SUCCESS;
267}
268
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200269DEFUN(cfg_stats_reporter_statsd, cfg_stats_reporter_statsd_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300270 "stats reporter statsd [NAME]",
271 CFG_STATS_STR CFG_REPORTER_STR
272 "Report to a STATSD server\n"
273 "Name of the reporter\n")
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200274{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100275 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300276 const char *name = NULL;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200277
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300278 if (argc > 0)
279 name = argv[0];
280
281 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, name);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200282 if (!srep) {
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300283 srep = osmo_stats_reporter_create_statsd(name);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200284 if (!srep) {
285 vty_out(vty, "%% Unable to create statsd reporter%s",
286 VTY_NEWLINE);
287 return CMD_WARNING;
288 }
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100289 srep->max_class = OSMO_STATS_CLASS_GLOBAL;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100290 /* TODO: if needed, add osmo_stats_add_reporter(srep); */
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200291 }
292
293 vty->index = srep;
294 vty->node = CFG_STATS_NODE;
295
296 return CMD_SUCCESS;
297}
298
299DEFUN(cfg_no_stats_reporter_statsd, cfg_no_stats_reporter_statsd_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300300 "no stats reporter statsd [NAME]",
301 NO_STR CFG_STATS_STR CFG_REPORTER_STR
302 "Report to a STATSD server\n"
303 "Name of the reporter\n")
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200304{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100305 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300306 const char *name = NULL;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200307
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300308 if (argc > 0)
309 name = argv[0];
310
311 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, name);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200312 if (!srep) {
Vadim Yanitskiy52a5c112021-11-09 13:59:20 +0300313 vty_out(vty, "%% There is no such statsd reporter with name '%s'%s",
314 name ? name : "", VTY_NEWLINE);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200315 return CMD_WARNING;
316 }
317
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100318 osmo_stats_reporter_free(srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200319
320 return CMD_SUCCESS;
321}
322
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100323DEFUN(cfg_stats_reporter_log, cfg_stats_reporter_log_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300324 "stats reporter log [NAME]",
325 CFG_STATS_STR CFG_REPORTER_STR
326 "Report to the logger\n"
327 "Name of the reporter\n")
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100328{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100329 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300330 const char *name = NULL;
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100331
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300332 if (argc > 0)
333 name = argv[0];
334
335 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, name);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100336 if (!srep) {
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300337 srep = osmo_stats_reporter_create_log(name);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100338 if (!srep) {
339 vty_out(vty, "%% Unable to create log reporter%s",
340 VTY_NEWLINE);
341 return CMD_WARNING;
342 }
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100343 srep->max_class = OSMO_STATS_CLASS_GLOBAL;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100344 /* TODO: if needed, add osmo_stats_add_reporter(srep); */
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100345 }
346
347 vty->index = srep;
348 vty->node = CFG_STATS_NODE;
349
350 return CMD_SUCCESS;
351}
352
353DEFUN(cfg_no_stats_reporter_log, cfg_no_stats_reporter_log_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300354 "no stats reporter log [NAME]",
355 NO_STR CFG_STATS_STR CFG_REPORTER_STR
356 "Report to the logger\n"
357 "Name of the reporter\n")
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100358{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100359 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300360 const char *name = NULL;
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100361
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300362 if (argc > 0)
363 name = argv[0];
364
365 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, name);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100366 if (!srep) {
Vadim Yanitskiy52a5c112021-11-09 13:59:20 +0300367 vty_out(vty, "%% There is no such log reporter with name '%s'%s",
368 name ? name : "", VTY_NEWLINE);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100369 return CMD_WARNING;
370 }
371
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100372 osmo_stats_reporter_free(srep);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100373
374 return CMD_SUCCESS;
375}
376
Alexander Chemeris161adee2020-05-08 18:19:24 +0300377DEFUN(cfg_stats_interval, cfg_stats_interval_cmd,
Daniel Willmann1a1de332020-07-14 18:11:14 +0200378 "stats interval <0-65535>",
Alexander Chemeris161adee2020-05-08 18:19:24 +0300379 CFG_STATS_STR "Set the reporting interval\n"
Daniel Willmann1a1de332020-07-14 18:11:14 +0200380 "Interval in seconds (0 disables the reporting interval)\n")
Alexander Chemeris161adee2020-05-08 18:19:24 +0300381{
382 int rc;
383 int interval = atoi(argv[0]);
384 rc = osmo_stats_set_interval(interval);
385 if (rc < 0) {
386 vty_out(vty, "%% Unable to set interval: %s%s",
387 strerror(-rc), VTY_NEWLINE);
388 return CMD_WARNING;
389 }
390
391 return CMD_SUCCESS;
392}
393
Philipp Maierb1ef8f52021-12-06 16:31:02 +0100394DEFUN(cfg_tcp_stats_interval, cfg_tcp_stats_interval_cmd,
395 "stats-tcp interval <0-65535>",
396 CFG_STATS_STR "Set the tcp socket stats polling interval\n"
397 "Interval in seconds (0 disables the polling interval)\n")
398{
399 int rc;
400 int interval = atoi(argv[0]);
401 rc = osmo_stats_tcp_set_interval(interval);
402 if (rc < 0) {
403 vty_out(vty, "%% Unable to set interval: %s%s",
404 strerror(-rc), VTY_NEWLINE);
405 return CMD_WARNING;
406 }
407
408 return CMD_SUCCESS;
409}
410
411DEFUN(cfg_tcp_stats_batch_size, cfg_tcp_stats_batch_size_cmd,
412 "stats-tcp batch-size <1-65535>",
413 CFG_STATS_STR "Set the number of tcp sockets that are processed per stats polling interval\n"
414 "Number of sockets per interval\n")
415{
416 osmo_tcp_stats_config->batch_size = atoi(argv[0]);
417 return CMD_SUCCESS;
418}
419
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200420DEFUN(show_stats,
421 show_stats_cmd,
Harald Welte3b007f82022-04-18 11:39:08 +0200422 "show stats [skip-zero]",
423 SHOW_STR SHOW_STATS_STR SKIP_ZERO_STR)
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200424{
Harald Welte3b007f82022-04-18 11:39:08 +0200425 bool skip_zero = false;
426 if (argc > 0)
427 skip_zero = true;
428
429 vty_out_statistics_full2(vty, "", skip_zero);
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200430
431 return CMD_SUCCESS;
432}
433
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100434DEFUN(show_stats_level,
435 show_stats_level_cmd,
Harald Welte3b007f82022-04-18 11:39:08 +0200436 "show stats level (global|peer|subscriber) [skip-zero]",
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100437 SHOW_STR SHOW_STATS_STR
Holger Hans Peter Freyther83481942015-11-07 21:10:01 +0100438 "Set the maximum group level\n"
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100439 "Show global groups only\n"
440 "Show global and network peer related groups\n"
Harald Welte3b007f82022-04-18 11:39:08 +0200441 "Show global, peer, and subscriber groups\n" SKIP_ZERO_STR)
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100442{
443 int level = get_string_value(stats_class_strs, argv[0]);
Harald Welte3b007f82022-04-18 11:39:08 +0200444 bool skip_zero = false;
445 if (argc > 1)
446 skip_zero = true;
447 vty_out_statistics_partial2(vty, "", level, skip_zero);
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100448
449 return CMD_SUCCESS;
450}
451
Alexander Couzensad580ba2016-05-16 16:01:45 +0200452static int asciidoc_handle_counter(struct osmo_counter *counter, void *sctx_)
453{
454 struct vty *vty = sctx_;
455 char *name = osmo_asciidoc_escape(counter->name);
456 char *description = osmo_asciidoc_escape(counter->description);
457
458 /* | name | This document & | description | */
459 vty_out(vty, "| %s | <<ungroup_counter_%s>> | %s%s",
460 name,
461 name,
462 description ? description : "",
463 VTY_NEWLINE);
464
465 talloc_free(name);
466 talloc_free(description);
467
468 return 0;
469}
470
471static void asciidoc_counter_generate(struct vty *vty)
472{
473 vty_out(vty, "// ungrouped osmo_counters%s", VTY_NEWLINE);
474 vty_out(vty, ".ungrouped osmo counters%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200475 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200476 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200477 vty_out(vty, "| Name | Reference | Description%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200478 osmo_counters_for_each(asciidoc_handle_counter, vty);
479 vty_out(vty, "|===%s", VTY_NEWLINE);
480}
481
482static int asciidoc_rate_ctr_handler(
483 struct rate_ctr_group *ctrg, struct rate_ctr *ctr,
484 const struct rate_ctr_desc *desc, void *sctx_)
485{
486 struct vty *vty = sctx_;
487 char *name = osmo_asciidoc_escape(desc->name);
488 char *description = osmo_asciidoc_escape(desc->description);
489 char *group_name_prefix = osmo_asciidoc_escape(ctrg->desc->group_name_prefix);
490
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200491 /* | Name | This document & | Description | */
Alexander Couzensad580ba2016-05-16 16:01:45 +0200492 vty_out(vty, "| %s | <<%s_%s>> | %s%s",
493 name,
494 group_name_prefix,
495 name,
496 description ? description : NULL,
497 VTY_NEWLINE);
498
499 /* description seems to be optional */
500 talloc_free(name);
501 talloc_free(group_name_prefix);
502 talloc_free(description);
503
504 return 0;
505}
506
507static int asciidoc_rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
508{
509 struct vty *vty = sctx_;
510
511 char *group_description = osmo_asciidoc_escape(ctrg->desc->group_description);
512 char *group_name_prefix = osmo_asciidoc_escape(ctrg->desc->group_name_prefix);
513
514 vty_out(vty, "// rate_ctr_group table %s%s", group_description, VTY_NEWLINE);
Pau Espin Pedrol18e019e2019-06-19 14:24:27 +0200515 vty_out(vty, ".%s - %s%s", group_name_prefix, group_description, VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200516 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200517 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200518 vty_out(vty, "| Name | Reference | Description%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200519 rate_ctr_for_each_counter(ctrg, asciidoc_rate_ctr_handler, sctx_);
520 vty_out(vty, "|===%s", VTY_NEWLINE);
521
522 talloc_free(group_name_prefix);
523 talloc_free(group_description);
524
525 return 0;
526}
527
528static int asciidoc_osmo_stat_item_handler(
529 struct osmo_stat_item_group *statg, struct osmo_stat_item *item, void *sctx_)
530{
531 struct vty *vty = sctx_;
532
Neels Hofmeyre90c7172021-09-14 14:37:38 +0200533 const struct osmo_stat_item_desc *desc = osmo_stat_item_get_desc(item);
534 char *name = osmo_asciidoc_escape(desc->name);
535 char *description = osmo_asciidoc_escape(desc->description);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200536 char *group_name_prefix = osmo_asciidoc_escape(statg->desc->group_name_prefix);
Neels Hofmeyre90c7172021-09-14 14:37:38 +0200537 char *unit = osmo_asciidoc_escape(desc->unit);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200538
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200539 /* | Name | Reference | Description | Unit | */
Alexander Couzensad580ba2016-05-16 16:01:45 +0200540 vty_out(vty, "| %s | <<%s_%s>> | %s | %s%s",
541 name,
542 group_name_prefix,
543 name,
544 description ? description : "",
545 unit ? unit : "",
546 VTY_NEWLINE);
547
548 talloc_free(name);
549 talloc_free(group_name_prefix);
550 talloc_free(description);
551 talloc_free(unit);
552
553 return 0;
554}
555
556static int asciidoc_osmo_stat_item_group_handler(struct osmo_stat_item_group *statg, void *sctx_)
557{
558 char *group_name_prefix = osmo_asciidoc_escape(statg->desc->group_name_prefix);
559 char *group_description = osmo_asciidoc_escape(statg->desc->group_description);
560
561 struct vty *vty = sctx_;
562 vty_out(vty, "%s%s", group_description ? group_description : "" , VTY_NEWLINE);
563
564 vty_out(vty, "// osmo_stat_item_group table %s%s", group_description ? group_description : "", VTY_NEWLINE);
Pau Espin Pedrol18e019e2019-06-19 14:24:27 +0200565 vty_out(vty, ".%s - %s%s", group_name_prefix, group_description ? group_description : "", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200566 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200567 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200568 vty_out(vty, "| Name | Reference | Description | Unit%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200569 osmo_stat_item_for_each_item(statg, asciidoc_osmo_stat_item_handler, sctx_);
570 vty_out(vty, "|===%s", VTY_NEWLINE);
571
572 talloc_free(group_name_prefix);
573 talloc_free(group_description);
574
575 return 0;
576}
577
578DEFUN(show_stats_asciidoc_table,
579 show_stats_asciidoc_table_cmd,
580 "show asciidoc counters",
Harald Weltef624c332016-06-15 11:35:16 +0200581 SHOW_STR "Asciidoc generation\n" "Generate table of all registered counters\n")
Alexander Couzensad580ba2016-05-16 16:01:45 +0200582{
Alexander Couzense052dc22016-10-04 18:04:37 +0200583 vty_out(vty, "// autogenerated by show asciidoc counters%s", VTY_NEWLINE);
Daniel Willmann6f3bbd42019-07-25 11:33:50 +0200584 vty_out(vty, "These counters and their description are based on %s %s (%s).%s%s",
Alexander Couzense052dc22016-10-04 18:04:37 +0200585 host.app_info->name,
586 host.app_info->version,
587 host.app_info->name ? host.app_info->name : "", VTY_NEWLINE, VTY_NEWLINE);
588 /* 2x VTY_NEWLINE are intentional otherwise it would interpret the first table header
589 * as usual text*/
Daniel Willmannd910a352018-07-24 20:01:26 +0200590 vty_out(vty, "=== Rate Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200591 vty_out(vty, "// generating tables for rate_ctr_group%s", VTY_NEWLINE);
592 rate_ctr_for_each_group(asciidoc_rate_ctr_group_handler, vty);
593
Daniel Willmann81588822021-06-16 14:19:48 +0200594 vty_out(vty, "=== Osmo Stat Items%s%s", VTY_NEWLINE, VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200595 vty_out(vty, "// generating tables for osmo_stat_items%s", VTY_NEWLINE);
596 osmo_stat_item_for_each_group(asciidoc_osmo_stat_item_group_handler, vty);
597
Daniel Willmann81588822021-06-16 14:19:48 +0200598 if (osmo_counters_count() == 0)
599 {
600 vty_out(vty, "// there are no ungrouped osmo_counters%s",
601 VTY_NEWLINE);
602 } else {
603 vty_out(vty, "=== Osmo Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
604 vty_out(vty, "// generating tables for osmo_counters%s", VTY_NEWLINE);
605 asciidoc_counter_generate(vty);
606 }
Alexander Couzensad580ba2016-05-16 16:01:45 +0200607 return CMD_SUCCESS;
608}
609
Harald Welte3b007f82022-04-18 11:39:08 +0200610struct rctr_vty_ctx {
611 struct vty *vty;
612 bool skip_zero;
613};
614
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200615static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
616{
Harald Welte3b007f82022-04-18 11:39:08 +0200617 struct rctr_vty_ctx *sctx = sctx_;
618 struct vty *vty = sctx->vty;
Vadim Yanitskiye9fd81a2021-06-06 18:02:57 +0200619 vty_out(vty, "%s %u", ctrg->desc->group_description, ctrg->idx);
620 if (ctrg->name != NULL)
621 vty_out(vty, " (%s)", ctrg->name);
622 vty_out(vty, ":%s", VTY_NEWLINE);
Harald Welte3b007f82022-04-18 11:39:08 +0200623 vty_out_rate_ctr_group_fmt2(vty, "%25n: %10c (%S/s %M/m %H/h %D/d) %d", ctrg, sctx->skip_zero);
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200624 return 0;
625}
626
627DEFUN(show_rate_counters,
628 show_rate_counters_cmd,
Harald Welte3b007f82022-04-18 11:39:08 +0200629 "show rate-counters [skip-zero]",
630 SHOW_STR "Show all rate counters\n" SKIP_ZERO_STR)
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200631{
Harald Welte3b007f82022-04-18 11:39:08 +0200632 struct rctr_vty_ctx rctx = { .vty = vty, .skip_zero = false };
633 if (argc > 0)
634 rctx.skip_zero = true;
635 rate_ctr_for_each_group(rate_ctr_group_handler, &rctx);
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200636 return CMD_SUCCESS;
637}
638
Daniel Willmann1a1de332020-07-14 18:11:14 +0200639DEFUN(stats_report,
640 stats_report_cmd,
641 "stats report",
642 STATS_STR "Manurally trigger reporting of stats\n")
643{
644 osmo_stats_report();
645 return CMD_SUCCESS;
646}
647
648static int reset_rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
649{
650 rate_ctr_group_reset(ctrg);
651 return 0;
652}
653
Daniel Willmann1a1de332020-07-14 18:11:14 +0200654DEFUN(stats_reset,
655 stats_reset_cmd,
656 "stats reset",
Neels Hofmeyr923cb842021-08-20 17:09:38 +0200657 STATS_STR "Reset all rate counter stats\n")
Daniel Willmann1a1de332020-07-14 18:11:14 +0200658{
659 rate_ctr_for_each_group(reset_rate_ctr_group_handler, NULL);
Daniel Willmann1a1de332020-07-14 18:11:14 +0200660 return CMD_SUCCESS;
661}
662
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100663static int config_write_stats_reporter(struct vty *vty, struct osmo_stats_reporter *srep)
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200664{
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300665 const char *type = NULL;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200666
667 switch (srep->type) {
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100668 case OSMO_STATS_REPORTER_STATSD:
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300669 type = "statsd";
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200670 break;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100671 case OSMO_STATS_REPORTER_LOG:
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300672 type = "log";
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100673 break;
Harald Welte8f25fd22022-05-08 09:57:39 +0200674 default:
675 /* don't try to save unknown stats reporters to the VTY. Imagine some
676 * application registering a new application specific stats reporter that
677 * this VTY code knows nothing about! */
678 return 0;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200679 }
680
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300681 vty_out(vty, "stats reporter %s", type);
682 if (srep->name != NULL)
683 vty_out(vty, " %s", srep->name);
684 vty_out(vty, "%s", VTY_NEWLINE);
685
Jacob Erlbecked197fd2015-10-27 14:43:24 +0100686 if (srep->have_net_config) {
687 if (srep->dest_addr_str)
688 vty_out(vty, " remote-ip %s%s",
689 srep->dest_addr_str, VTY_NEWLINE);
690 if (srep->dest_port)
691 vty_out(vty, " remote-port %d%s",
692 srep->dest_port, VTY_NEWLINE);
693 if (srep->bind_addr_str)
694 vty_out(vty, " local-ip %s%s",
695 srep->bind_addr_str, VTY_NEWLINE);
696 if (srep->mtu)
697 vty_out(vty, " mtu %d%s",
698 srep->mtu, VTY_NEWLINE);
699 }
700
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100701 if (srep->max_class)
702 vty_out(vty, " level %s%s",
703 get_value_string(stats_class_strs, srep->max_class),
704 VTY_NEWLINE);
705
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200706 if (srep->name_prefix && *srep->name_prefix)
707 vty_out(vty, " prefix %s%s",
708 srep->name_prefix, VTY_NEWLINE);
709 else
710 vty_out(vty, " no prefix%s", VTY_NEWLINE);
711
Alexander Chemerisdfebf402020-05-08 19:10:40 +0300712 if (srep->flush_period > 0)
713 vty_out(vty, " flush-period %d%s",
714 srep->flush_period, VTY_NEWLINE);
715
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200716 if (srep->enabled)
717 vty_out(vty, " enable%s", VTY_NEWLINE);
Vadim Yanitskiyd6b00592021-11-09 13:46:55 +0300718 else
719 vty_out(vty, " disable%s", VTY_NEWLINE);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200720
721 return 1;
722}
723
724static int config_write_stats(struct vty *vty)
725{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100726 struct osmo_stats_reporter *srep;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200727
Vadim Yanitskiy4f1c4e32021-11-09 13:38:40 +0300728 vty_out(vty, "stats interval %d%s", osmo_stats_config->interval, VTY_NEWLINE);
Philipp Maierb1ef8f52021-12-06 16:31:02 +0100729 if (osmo_tcp_stats_config->interval != TCP_STATS_DEFAULT_INTERVAL)
730 vty_out(vty, "stats-tcp interval %d%s", osmo_tcp_stats_config->interval, VTY_NEWLINE);
731 if (osmo_tcp_stats_config->batch_size != TCP_STATS_DEFAULT_BATCH_SIZE)
732 vty_out(vty, "stats-tcp batch-size %d%s", osmo_tcp_stats_config->batch_size, VTY_NEWLINE);
Vadim Yanitskiy4f1c4e32021-11-09 13:38:40 +0300733
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300734 /* Loop through all reporters */
735 llist_for_each_entry(srep, &osmo_stats_reporter_list, list)
736 config_write_stats_reporter(vty, srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200737
738 return 1;
739}
740
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200741/*! Add stats related commands to the VTY
Harald Welte96e2a002017-06-12 21:44:18 +0200742 * Call this once during your application initialization if you would
743 * like to have stats VTY commands enabled.
744 */
Harald Weltee61d4592022-11-03 11:05:58 +0100745void osmo_stats_vty_add_cmds(void)
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200746{
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700747 install_lib_element_ve(&show_stats_cmd);
748 install_lib_element_ve(&show_stats_level_cmd);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200749
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700750 install_lib_element(CONFIG_NODE, &cfg_stats_reporter_statsd_cmd);
751 install_lib_element(CONFIG_NODE, &cfg_no_stats_reporter_statsd_cmd);
752 install_lib_element(CONFIG_NODE, &cfg_stats_reporter_log_cmd);
753 install_lib_element(CONFIG_NODE, &cfg_no_stats_reporter_log_cmd);
754 install_lib_element(CONFIG_NODE, &cfg_stats_interval_cmd);
Philipp Maierb1ef8f52021-12-06 16:31:02 +0100755 install_lib_element(CONFIG_NODE, &cfg_tcp_stats_interval_cmd);
756 install_lib_element(CONFIG_NODE, &cfg_tcp_stats_batch_size_cmd);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200757
758 install_node(&cfg_stats_node, config_write_stats);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200759
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700760 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_local_ip_cmd);
761 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_local_ip_cmd);
762 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_ip_cmd);
763 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_port_cmd);
764 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_mtu_cmd);
765 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_mtu_cmd);
766 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_prefix_cmd);
767 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_prefix_cmd);
768 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_level_cmd);
769 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_enable_cmd);
770 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_disable_cmd);
771 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_flush_period_cmd);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200772
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700773 install_lib_element_ve(&show_stats_asciidoc_table_cmd);
774 install_lib_element_ve(&show_rate_counters_cmd);
Daniel Willmann1a1de332020-07-14 18:11:14 +0200775
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700776 install_lib_element(ENABLE_NODE, &stats_report_cmd);
777 install_lib_element(ENABLE_NODE, &stats_reset_cmd);
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200778}