blob: 308bab679207600d7da4f6510173702d9bb24370 [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*
2 * (C) 2009-2010 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 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25#include <stdlib.h>
26#include <string.h>
27
28#include "../../config.h"
29
30#include <osmocom/vty/command.h>
31#include <osmocom/vty/buffer.h>
32#include <osmocom/vty/vty.h>
33#include <osmocom/vty/telnet_interface.h>
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020034#include <osmocom/vty/telnet_interface.h>
Jacob Erlbeck45513e62015-10-19 15:14:13 +020035#include <osmocom/vty/misc.h>
36
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020037#include <osmocom/core/stats.h>
Harald Welte216338c2017-10-15 19:46:19 +020038#include <osmocom/core/counter.h>
Alexander Couzensad580ba2016-05-16 16:01:45 +020039#include <osmocom/core/rate_ctr.h>
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020040
Jacob Erlbeck45513e62015-10-19 15:14:13 +020041#define CFG_STATS_STR "Configure stats sub-system\n"
42#define CFG_REPORTER_STR "Configure a stats reporter\n"
43
44#define SHOW_STATS_STR "Show statistical values\n"
45
Daniel Willmann1a1de332020-07-14 18:11:14 +020046#define STATS_STR "Stats related commands\n"
47
Harald Welte8c648252017-10-16 15:17:03 +020048/*! \file stats_vty.c
Neels Hofmeyr87e45502017-06-20 00:17:59 +020049 * VTY interface for statsd / statistic items
Harald Welte8c648252017-10-16 15:17:03 +020050 *
51 * This code allows you to register a couple of VTY commands that
52 * permit configuration of the \ref stats functionality from the VTY.
53 *
54 * Use \ref osmo_stats_vty_add_cmds once at application start-up to
55 * enable related commands.
Harald Welte96e2a002017-06-12 21:44:18 +020056 */
57
Alexander Couzense052dc22016-10-04 18:04:37 +020058/* containing version info */
59extern struct host host;
60
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020061struct cmd_node cfg_stats_node = {
62 CFG_STATS_NODE,
63 "%s(config-stats)# ",
64 1
65};
66
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +010067static const struct value_string stats_class_strs[] = {
68 { OSMO_STATS_CLASS_GLOBAL, "global" },
69 { OSMO_STATS_CLASS_PEER, "peer" },
70 { OSMO_STATS_CLASS_SUBSCRIBER, "subscriber" },
71 { 0, NULL }
72};
73
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +010074static struct osmo_stats_reporter *osmo_stats_vty2srep(struct vty *vty)
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020075{
76 if (vty->node == CFG_STATS_NODE)
77 return vty->index;
78
79 return NULL;
80}
81
82static int set_srep_parameter_str(struct vty *vty,
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +010083 int (*fun)(struct osmo_stats_reporter *, const char *),
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020084 const char *val, const char *param_name)
85{
86 int rc;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +010087 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +020088 OSMO_ASSERT(srep);
89
90 rc = fun(srep, val);
91 if (rc < 0) {
92 vty_out(vty, "%% Unable to set %s: %s%s",
93 param_name, strerror(-rc), VTY_NEWLINE);
94 return CMD_WARNING;
95 }
96
97 return CMD_SUCCESS;
98}
99
100static int set_srep_parameter_int(struct vty *vty,
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100101 int (*fun)(struct osmo_stats_reporter *, int),
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200102 const char *val, const char *param_name)
103{
104 int rc;
105 int int_val;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100106 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200107 OSMO_ASSERT(srep);
108
109 int_val = atoi(val);
110
111 rc = fun(srep, int_val);
112 if (rc < 0) {
113 vty_out(vty, "%% Unable to set %s: %s%s",
114 param_name, strerror(-rc), VTY_NEWLINE);
115 return CMD_WARNING;
116 }
117
118 return CMD_SUCCESS;
119}
120
121DEFUN(cfg_stats_reporter_local_ip, cfg_stats_reporter_local_ip_cmd,
122 "local-ip ADDR",
123 "Set the IP address to which we bind locally\n"
124 "IP Address\n")
125{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100126 return set_srep_parameter_str(vty, osmo_stats_reporter_set_local_addr,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200127 argv[0], "local address");
128}
129
130DEFUN(cfg_no_stats_reporter_local_ip, cfg_no_stats_reporter_local_ip_cmd,
131 "no local-ip",
132 NO_STR
133 "Set the IP address to which we bind locally\n")
134{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100135 return set_srep_parameter_str(vty, osmo_stats_reporter_set_local_addr,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200136 NULL, "local address");
137}
138
139DEFUN(cfg_stats_reporter_remote_ip, cfg_stats_reporter_remote_ip_cmd,
140 "remote-ip ADDR",
141 "Set the remote IP address to which we connect\n"
142 "IP Address\n")
143{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100144 return set_srep_parameter_str(vty, osmo_stats_reporter_set_remote_addr,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200145 argv[0], "remote address");
146}
147
148DEFUN(cfg_stats_reporter_remote_port, cfg_stats_reporter_remote_port_cmd,
149 "remote-port <1-65535>",
150 "Set the remote port to which we connect\n"
151 "Remote port number\n")
152{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100153 return set_srep_parameter_int(vty, osmo_stats_reporter_set_remote_port,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200154 argv[0], "remote port");
155}
156
Jacob Erlbeckd01acfc2015-10-26 16:22:45 +0100157DEFUN(cfg_stats_reporter_mtu, cfg_stats_reporter_mtu_cmd,
158 "mtu <100-65535>",
159 "Set the maximum packet size\n"
160 "Size in byte\n")
161{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100162 return set_srep_parameter_int(vty, osmo_stats_reporter_set_mtu,
Jacob Erlbeckd01acfc2015-10-26 16:22:45 +0100163 argv[0], "mtu");
164}
165
166DEFUN(cfg_no_stats_reporter_mtu, cfg_no_stats_reporter_mtu_cmd,
167 "no mtu",
168 NO_STR "Set the maximum packet size\n")
169{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100170 return set_srep_parameter_int(vty, osmo_stats_reporter_set_mtu,
Holger Hans Peter Freyther8f0374f2015-11-02 15:53:09 +0100171 "0", "mtu");
Jacob Erlbeckd01acfc2015-10-26 16:22:45 +0100172}
173
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200174DEFUN(cfg_stats_reporter_prefix, cfg_stats_reporter_prefix_cmd,
175 "prefix PREFIX",
176 "Set the item name prefix\n"
177 "The prefix string\n")
178{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100179 return set_srep_parameter_str(vty, osmo_stats_reporter_set_name_prefix,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200180 argv[0], "prefix string");
181}
182
183DEFUN(cfg_no_stats_reporter_prefix, cfg_no_stats_reporter_prefix_cmd,
184 "no prefix",
185 NO_STR
186 "Set the item name prefix\n")
187{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100188 return set_srep_parameter_str(vty, osmo_stats_reporter_set_name_prefix,
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200189 "", "prefix string");
190}
191
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100192DEFUN(cfg_stats_reporter_level, cfg_stats_reporter_level_cmd,
193 "level (global|peer|subscriber)",
194 "Set the maximum group level\n"
195 "Report global groups only\n"
196 "Report global and network peer related groups\n"
197 "Report global, peer, and subscriber groups\n")
198{
199 int level = get_string_value(stats_class_strs, argv[0]);
200 int rc;
201 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
202
203 OSMO_ASSERT(srep);
204 rc = osmo_stats_reporter_set_max_class(srep, level);
205 if (rc < 0) {
206 vty_out(vty, "%% Unable to set level: %s%s",
207 strerror(-rc), VTY_NEWLINE);
208 return CMD_WARNING;
209 }
210
211 return 0;
212}
213
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200214DEFUN(cfg_stats_reporter_enable, cfg_stats_reporter_enable_cmd,
215 "enable",
216 "Enable the reporter\n")
217{
218 int rc;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100219 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200220 OSMO_ASSERT(srep);
221
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100222 rc = osmo_stats_reporter_enable(srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200223 if (rc < 0) {
224 vty_out(vty, "%% Unable to enable the reporter: %s%s",
225 strerror(-rc), VTY_NEWLINE);
226 return CMD_WARNING;
227 }
228
229 return CMD_SUCCESS;
230}
231
232DEFUN(cfg_stats_reporter_disable, cfg_stats_reporter_disable_cmd,
233 "disable",
234 "Disable the reporter\n")
235{
236 int rc;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100237 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200238 OSMO_ASSERT(srep);
239
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100240 rc = osmo_stats_reporter_disable(srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200241 if (rc < 0) {
242 vty_out(vty, "%% Unable to disable the reporter: %s%s",
243 strerror(-rc), VTY_NEWLINE);
244 return CMD_WARNING;
245 }
246
247 return CMD_SUCCESS;
248}
249
Alexander Chemerisdfebf402020-05-08 19:10:40 +0300250DEFUN(cfg_stats_reporter_flush_period, cfg_stats_reporter_flush_period_cmd,
251 "flush-period <0-65535>",
252 CFG_STATS_STR "Send all stats even if they have not changed (i.e. force the flush)"
253 "every N-th reporting interval. Set to 0 to disable regular flush (default).\n"
254 "0 to disable regular flush (default), 1 to flush every time, 2 to flush every 2nd time, etc\n")
255{
256 int rc;
257 unsigned int period = atoi(argv[0]);
258 struct osmo_stats_reporter *srep = osmo_stats_vty2srep(vty);
259 OSMO_ASSERT(srep);
260
261 rc = osmo_stats_reporter_set_flush_period(srep, period);
262 if (rc < 0) {
263 vty_out(vty, "%% Unable to set force flush period: %s%s",
264 strerror(-rc), VTY_NEWLINE);
265 return CMD_WARNING;
266 }
267
268 return CMD_SUCCESS;
269}
270
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200271DEFUN(cfg_stats_reporter_statsd, cfg_stats_reporter_statsd_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300272 "stats reporter statsd [NAME]",
273 CFG_STATS_STR CFG_REPORTER_STR
274 "Report to a STATSD server\n"
275 "Name of the reporter\n")
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200276{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100277 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300278 const char *name = NULL;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200279
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300280 if (argc > 0)
281 name = argv[0];
282
283 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, name);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200284 if (!srep) {
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300285 srep = osmo_stats_reporter_create_statsd(name);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200286 if (!srep) {
287 vty_out(vty, "%% Unable to create statsd reporter%s",
288 VTY_NEWLINE);
289 return CMD_WARNING;
290 }
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100291 srep->max_class = OSMO_STATS_CLASS_GLOBAL;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100292 /* TODO: if needed, add osmo_stats_add_reporter(srep); */
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200293 }
294
295 vty->index = srep;
296 vty->node = CFG_STATS_NODE;
297
298 return CMD_SUCCESS;
299}
300
301DEFUN(cfg_no_stats_reporter_statsd, cfg_no_stats_reporter_statsd_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300302 "no stats reporter statsd [NAME]",
303 NO_STR CFG_STATS_STR CFG_REPORTER_STR
304 "Report to a STATSD server\n"
305 "Name of the reporter\n")
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200306{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100307 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300308 const char *name = NULL;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200309
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300310 if (argc > 0)
311 name = argv[0];
312
313 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, name);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200314 if (!srep) {
315 vty_out(vty, "%% No statsd logging active%s",
316 VTY_NEWLINE);
317 return CMD_WARNING;
318 }
319
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100320 osmo_stats_reporter_free(srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200321
322 return CMD_SUCCESS;
323}
324
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100325DEFUN(cfg_stats_reporter_log, cfg_stats_reporter_log_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300326 "stats reporter log [NAME]",
327 CFG_STATS_STR CFG_REPORTER_STR
328 "Report to the logger\n"
329 "Name of the reporter\n")
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100330{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100331 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300332 const char *name = NULL;
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100333
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300334 if (argc > 0)
335 name = argv[0];
336
337 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, name);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100338 if (!srep) {
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300339 srep = osmo_stats_reporter_create_log(name);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100340 if (!srep) {
341 vty_out(vty, "%% Unable to create log reporter%s",
342 VTY_NEWLINE);
343 return CMD_WARNING;
344 }
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100345 srep->max_class = OSMO_STATS_CLASS_GLOBAL;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100346 /* TODO: if needed, add osmo_stats_add_reporter(srep); */
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100347 }
348
349 vty->index = srep;
350 vty->node = CFG_STATS_NODE;
351
352 return CMD_SUCCESS;
353}
354
355DEFUN(cfg_no_stats_reporter_log, cfg_no_stats_reporter_log_cmd,
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300356 "no stats reporter log [NAME]",
357 NO_STR CFG_STATS_STR CFG_REPORTER_STR
358 "Report to the logger\n"
359 "Name of the reporter\n")
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100360{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100361 struct osmo_stats_reporter *srep;
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300362 const char *name = NULL;
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100363
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300364 if (argc > 0)
365 name = argv[0];
366
367 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, name);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100368 if (!srep) {
369 vty_out(vty, "%% No log reporting active%s",
370 VTY_NEWLINE);
371 return CMD_WARNING;
372 }
373
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100374 osmo_stats_reporter_free(srep);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100375
376 return CMD_SUCCESS;
377}
378
Alexander Chemeris161adee2020-05-08 18:19:24 +0300379DEFUN(cfg_stats_interval, cfg_stats_interval_cmd,
Daniel Willmann1a1de332020-07-14 18:11:14 +0200380 "stats interval <0-65535>",
Alexander Chemeris161adee2020-05-08 18:19:24 +0300381 CFG_STATS_STR "Set the reporting interval\n"
Daniel Willmann1a1de332020-07-14 18:11:14 +0200382 "Interval in seconds (0 disables the reporting interval)\n")
Alexander Chemeris161adee2020-05-08 18:19:24 +0300383{
384 int rc;
385 int interval = atoi(argv[0]);
386 rc = osmo_stats_set_interval(interval);
387 if (rc < 0) {
388 vty_out(vty, "%% Unable to set interval: %s%s",
389 strerror(-rc), VTY_NEWLINE);
390 return CMD_WARNING;
391 }
392
393 return CMD_SUCCESS;
394}
395
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200396DEFUN(show_stats,
397 show_stats_cmd,
398 "show stats",
399 SHOW_STR SHOW_STATS_STR)
400{
401 vty_out_statistics_full(vty, "");
402
403 return CMD_SUCCESS;
404}
405
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100406DEFUN(show_stats_level,
407 show_stats_level_cmd,
408 "show stats level (global|peer|subscriber)",
409 SHOW_STR SHOW_STATS_STR
Holger Hans Peter Freyther83481942015-11-07 21:10:01 +0100410 "Set the maximum group level\n"
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100411 "Show global groups only\n"
412 "Show global and network peer related groups\n"
413 "Show global, peer, and subscriber groups\n")
414{
415 int level = get_string_value(stats_class_strs, argv[0]);
416 vty_out_statistics_partial(vty, "", level);
417
418 return CMD_SUCCESS;
419}
420
Alexander Couzensad580ba2016-05-16 16:01:45 +0200421static int asciidoc_handle_counter(struct osmo_counter *counter, void *sctx_)
422{
423 struct vty *vty = sctx_;
424 char *name = osmo_asciidoc_escape(counter->name);
425 char *description = osmo_asciidoc_escape(counter->description);
426
427 /* | name | This document & | description | */
428 vty_out(vty, "| %s | <<ungroup_counter_%s>> | %s%s",
429 name,
430 name,
431 description ? description : "",
432 VTY_NEWLINE);
433
434 talloc_free(name);
435 talloc_free(description);
436
437 return 0;
438}
439
440static void asciidoc_counter_generate(struct vty *vty)
441{
442 vty_out(vty, "// ungrouped osmo_counters%s", VTY_NEWLINE);
443 vty_out(vty, ".ungrouped osmo counters%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200444 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200445 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200446 vty_out(vty, "| Name | Reference | Description%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200447 osmo_counters_for_each(asciidoc_handle_counter, vty);
448 vty_out(vty, "|===%s", VTY_NEWLINE);
449}
450
451static int asciidoc_rate_ctr_handler(
452 struct rate_ctr_group *ctrg, struct rate_ctr *ctr,
453 const struct rate_ctr_desc *desc, void *sctx_)
454{
455 struct vty *vty = sctx_;
456 char *name = osmo_asciidoc_escape(desc->name);
457 char *description = osmo_asciidoc_escape(desc->description);
458 char *group_name_prefix = osmo_asciidoc_escape(ctrg->desc->group_name_prefix);
459
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200460 /* | Name | This document & | Description | */
Alexander Couzensad580ba2016-05-16 16:01:45 +0200461 vty_out(vty, "| %s | <<%s_%s>> | %s%s",
462 name,
463 group_name_prefix,
464 name,
465 description ? description : NULL,
466 VTY_NEWLINE);
467
468 /* description seems to be optional */
469 talloc_free(name);
470 talloc_free(group_name_prefix);
471 talloc_free(description);
472
473 return 0;
474}
475
476static int asciidoc_rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
477{
478 struct vty *vty = sctx_;
479
480 char *group_description = osmo_asciidoc_escape(ctrg->desc->group_description);
481 char *group_name_prefix = osmo_asciidoc_escape(ctrg->desc->group_name_prefix);
482
483 vty_out(vty, "// rate_ctr_group table %s%s", group_description, VTY_NEWLINE);
Pau Espin Pedrol18e019e2019-06-19 14:24:27 +0200484 vty_out(vty, ".%s - %s%s", group_name_prefix, group_description, VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200485 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200486 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200487 vty_out(vty, "| Name | Reference | Description%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200488 rate_ctr_for_each_counter(ctrg, asciidoc_rate_ctr_handler, sctx_);
489 vty_out(vty, "|===%s", VTY_NEWLINE);
490
491 talloc_free(group_name_prefix);
492 talloc_free(group_description);
493
494 return 0;
495}
496
497static int asciidoc_osmo_stat_item_handler(
498 struct osmo_stat_item_group *statg, struct osmo_stat_item *item, void *sctx_)
499{
500 struct vty *vty = sctx_;
501
Neels Hofmeyre90c7172021-09-14 14:37:38 +0200502 const struct osmo_stat_item_desc *desc = osmo_stat_item_get_desc(item);
503 char *name = osmo_asciidoc_escape(desc->name);
504 char *description = osmo_asciidoc_escape(desc->description);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200505 char *group_name_prefix = osmo_asciidoc_escape(statg->desc->group_name_prefix);
Neels Hofmeyre90c7172021-09-14 14:37:38 +0200506 char *unit = osmo_asciidoc_escape(desc->unit);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200507
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200508 /* | Name | Reference | Description | Unit | */
Alexander Couzensad580ba2016-05-16 16:01:45 +0200509 vty_out(vty, "| %s | <<%s_%s>> | %s | %s%s",
510 name,
511 group_name_prefix,
512 name,
513 description ? description : "",
514 unit ? unit : "",
515 VTY_NEWLINE);
516
517 talloc_free(name);
518 talloc_free(group_name_prefix);
519 talloc_free(description);
520 talloc_free(unit);
521
522 return 0;
523}
524
525static int asciidoc_osmo_stat_item_group_handler(struct osmo_stat_item_group *statg, void *sctx_)
526{
527 char *group_name_prefix = osmo_asciidoc_escape(statg->desc->group_name_prefix);
528 char *group_description = osmo_asciidoc_escape(statg->desc->group_description);
529
530 struct vty *vty = sctx_;
531 vty_out(vty, "%s%s", group_description ? group_description : "" , VTY_NEWLINE);
532
533 vty_out(vty, "// osmo_stat_item_group table %s%s", group_description ? group_description : "", VTY_NEWLINE);
Pau Espin Pedrol18e019e2019-06-19 14:24:27 +0200534 vty_out(vty, ".%s - %s%s", group_name_prefix, group_description ? group_description : "", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200535 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200536 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200537 vty_out(vty, "| Name | Reference | Description | Unit%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200538 osmo_stat_item_for_each_item(statg, asciidoc_osmo_stat_item_handler, sctx_);
539 vty_out(vty, "|===%s", VTY_NEWLINE);
540
541 talloc_free(group_name_prefix);
542 talloc_free(group_description);
543
544 return 0;
545}
546
547DEFUN(show_stats_asciidoc_table,
548 show_stats_asciidoc_table_cmd,
549 "show asciidoc counters",
Harald Weltef624c332016-06-15 11:35:16 +0200550 SHOW_STR "Asciidoc generation\n" "Generate table of all registered counters\n")
Alexander Couzensad580ba2016-05-16 16:01:45 +0200551{
Alexander Couzense052dc22016-10-04 18:04:37 +0200552 vty_out(vty, "// autogenerated by show asciidoc counters%s", VTY_NEWLINE);
Daniel Willmann6f3bbd42019-07-25 11:33:50 +0200553 vty_out(vty, "These counters and their description are based on %s %s (%s).%s%s",
Alexander Couzense052dc22016-10-04 18:04:37 +0200554 host.app_info->name,
555 host.app_info->version,
556 host.app_info->name ? host.app_info->name : "", VTY_NEWLINE, VTY_NEWLINE);
557 /* 2x VTY_NEWLINE are intentional otherwise it would interpret the first table header
558 * as usual text*/
Daniel Willmannd910a352018-07-24 20:01:26 +0200559 vty_out(vty, "=== Rate Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200560 vty_out(vty, "// generating tables for rate_ctr_group%s", VTY_NEWLINE);
561 rate_ctr_for_each_group(asciidoc_rate_ctr_group_handler, vty);
562
Daniel Willmann81588822021-06-16 14:19:48 +0200563 vty_out(vty, "=== Osmo Stat Items%s%s", VTY_NEWLINE, VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200564 vty_out(vty, "// generating tables for osmo_stat_items%s", VTY_NEWLINE);
565 osmo_stat_item_for_each_group(asciidoc_osmo_stat_item_group_handler, vty);
566
Daniel Willmann81588822021-06-16 14:19:48 +0200567 if (osmo_counters_count() == 0)
568 {
569 vty_out(vty, "// there are no ungrouped osmo_counters%s",
570 VTY_NEWLINE);
571 } else {
572 vty_out(vty, "=== Osmo Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
573 vty_out(vty, "// generating tables for osmo_counters%s", VTY_NEWLINE);
574 asciidoc_counter_generate(vty);
575 }
Alexander Couzensad580ba2016-05-16 16:01:45 +0200576 return CMD_SUCCESS;
577}
578
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200579static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
580{
581 struct vty *vty = sctx_;
Vadim Yanitskiye9fd81a2021-06-06 18:02:57 +0200582 vty_out(vty, "%s %u", ctrg->desc->group_description, ctrg->idx);
583 if (ctrg->name != NULL)
584 vty_out(vty, " (%s)", ctrg->name);
585 vty_out(vty, ":%s", VTY_NEWLINE);
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200586 vty_out_rate_ctr_group_fmt(vty, "%25n: %10c (%S/s %M/m %H/h %D/d) %d", ctrg);
587 return 0;
588}
589
590DEFUN(show_rate_counters,
591 show_rate_counters_cmd,
592 "show rate-counters",
593 SHOW_STR "Show all rate counters\n")
594{
595 rate_ctr_for_each_group(rate_ctr_group_handler, vty);
596 return CMD_SUCCESS;
597}
598
Daniel Willmann1a1de332020-07-14 18:11:14 +0200599DEFUN(stats_report,
600 stats_report_cmd,
601 "stats report",
602 STATS_STR "Manurally trigger reporting of stats\n")
603{
604 osmo_stats_report();
605 return CMD_SUCCESS;
606}
607
608static int reset_rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
609{
610 rate_ctr_group_reset(ctrg);
611 return 0;
612}
613
Daniel Willmann1a1de332020-07-14 18:11:14 +0200614DEFUN(stats_reset,
615 stats_reset_cmd,
616 "stats reset",
Neels Hofmeyr923cb842021-08-20 17:09:38 +0200617 STATS_STR "Reset all rate counter stats\n")
Daniel Willmann1a1de332020-07-14 18:11:14 +0200618{
619 rate_ctr_for_each_group(reset_rate_ctr_group_handler, NULL);
Daniel Willmann1a1de332020-07-14 18:11:14 +0200620 return CMD_SUCCESS;
621}
622
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100623static int config_write_stats_reporter(struct vty *vty, struct osmo_stats_reporter *srep)
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200624{
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300625 const char *type = NULL;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200626
627 switch (srep->type) {
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100628 case OSMO_STATS_REPORTER_STATSD:
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300629 type = "statsd";
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200630 break;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100631 case OSMO_STATS_REPORTER_LOG:
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300632 type = "log";
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100633 break;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200634 }
635
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300636 vty_out(vty, "stats reporter %s", type);
637 if (srep->name != NULL)
638 vty_out(vty, " %s", srep->name);
639 vty_out(vty, "%s", VTY_NEWLINE);
640
Jacob Erlbecked197fd2015-10-27 14:43:24 +0100641 if (srep->have_net_config) {
642 if (srep->dest_addr_str)
643 vty_out(vty, " remote-ip %s%s",
644 srep->dest_addr_str, VTY_NEWLINE);
645 if (srep->dest_port)
646 vty_out(vty, " remote-port %d%s",
647 srep->dest_port, VTY_NEWLINE);
648 if (srep->bind_addr_str)
649 vty_out(vty, " local-ip %s%s",
650 srep->bind_addr_str, VTY_NEWLINE);
651 if (srep->mtu)
652 vty_out(vty, " mtu %d%s",
653 srep->mtu, VTY_NEWLINE);
654 }
655
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100656 if (srep->max_class)
657 vty_out(vty, " level %s%s",
658 get_value_string(stats_class_strs, srep->max_class),
659 VTY_NEWLINE);
660
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200661 if (srep->name_prefix && *srep->name_prefix)
662 vty_out(vty, " prefix %s%s",
663 srep->name_prefix, VTY_NEWLINE);
664 else
665 vty_out(vty, " no prefix%s", VTY_NEWLINE);
666
Alexander Chemerisdfebf402020-05-08 19:10:40 +0300667 if (srep->flush_period > 0)
668 vty_out(vty, " flush-period %d%s",
669 srep->flush_period, VTY_NEWLINE);
670
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200671 if (srep->enabled)
672 vty_out(vty, " enable%s", VTY_NEWLINE);
Vadim Yanitskiyd6b00592021-11-09 13:46:55 +0300673 else
674 vty_out(vty, " disable%s", VTY_NEWLINE);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200675
676 return 1;
677}
678
679static int config_write_stats(struct vty *vty)
680{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100681 struct osmo_stats_reporter *srep;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200682
Vadim Yanitskiy4f1c4e32021-11-09 13:38:40 +0300683 vty_out(vty, "stats interval %d%s", osmo_stats_config->interval, VTY_NEWLINE);
684
Vadim Yanitskiybfc83772021-11-08 23:14:29 +0300685 /* Loop through all reporters */
686 llist_for_each_entry(srep, &osmo_stats_reporter_list, list)
687 config_write_stats_reporter(vty, srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200688
689 return 1;
690}
691
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200692/*! Add stats related commands to the VTY
Harald Welte96e2a002017-06-12 21:44:18 +0200693 * Call this once during your application initialization if you would
694 * like to have stats VTY commands enabled.
695 */
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100696void osmo_stats_vty_add_cmds()
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200697{
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700698 install_lib_element_ve(&show_stats_cmd);
699 install_lib_element_ve(&show_stats_level_cmd);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200700
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700701 install_lib_element(CONFIG_NODE, &cfg_stats_reporter_statsd_cmd);
702 install_lib_element(CONFIG_NODE, &cfg_no_stats_reporter_statsd_cmd);
703 install_lib_element(CONFIG_NODE, &cfg_stats_reporter_log_cmd);
704 install_lib_element(CONFIG_NODE, &cfg_no_stats_reporter_log_cmd);
705 install_lib_element(CONFIG_NODE, &cfg_stats_interval_cmd);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200706
707 install_node(&cfg_stats_node, config_write_stats);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200708
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700709 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_local_ip_cmd);
710 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_local_ip_cmd);
711 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_ip_cmd);
712 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_port_cmd);
713 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_mtu_cmd);
714 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_mtu_cmd);
715 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_prefix_cmd);
716 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_prefix_cmd);
717 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_level_cmd);
718 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_enable_cmd);
719 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_disable_cmd);
720 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_flush_period_cmd);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200721
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700722 install_lib_element_ve(&show_stats_asciidoc_table_cmd);
723 install_lib_element_ve(&show_rate_counters_cmd);
Daniel Willmann1a1de332020-07-14 18:11:14 +0200724
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700725 install_lib_element(ENABLE_NODE, &stats_report_cmd);
726 install_lib_element(ENABLE_NODE, &stats_reset_cmd);
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200727}