blob: 17e7190dd5b967483e49ee66c3f9c90fa563a088 [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,
272 "stats reporter statsd",
273 CFG_STATS_STR CFG_REPORTER_STR "Report to a STATSD server\n")
274{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100275 struct osmo_stats_reporter *srep;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200276
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100277 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200278 if (!srep) {
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100279 srep = osmo_stats_reporter_create_statsd(NULL);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200280 if (!srep) {
281 vty_out(vty, "%% Unable to create statsd reporter%s",
282 VTY_NEWLINE);
283 return CMD_WARNING;
284 }
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100285 srep->max_class = OSMO_STATS_CLASS_GLOBAL;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100286 /* TODO: if needed, add osmo_stats_add_reporter(srep); */
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200287 }
288
289 vty->index = srep;
290 vty->node = CFG_STATS_NODE;
291
292 return CMD_SUCCESS;
293}
294
295DEFUN(cfg_no_stats_reporter_statsd, cfg_no_stats_reporter_statsd_cmd,
296 "no stats reporter statsd",
297 NO_STR CFG_STATS_STR CFG_REPORTER_STR "Report to a STATSD server\n")
298{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100299 struct osmo_stats_reporter *srep;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200300
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100301 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200302 if (!srep) {
303 vty_out(vty, "%% No statsd logging active%s",
304 VTY_NEWLINE);
305 return CMD_WARNING;
306 }
307
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100308 osmo_stats_reporter_free(srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200309
310 return CMD_SUCCESS;
311}
312
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100313DEFUN(cfg_stats_reporter_log, cfg_stats_reporter_log_cmd,
314 "stats reporter log",
315 CFG_STATS_STR CFG_REPORTER_STR "Report to the logger\n")
316{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100317 struct osmo_stats_reporter *srep;
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100318
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100319 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100320 if (!srep) {
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100321 srep = osmo_stats_reporter_create_log(NULL);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100322 if (!srep) {
323 vty_out(vty, "%% Unable to create log reporter%s",
324 VTY_NEWLINE);
325 return CMD_WARNING;
326 }
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100327 srep->max_class = OSMO_STATS_CLASS_GLOBAL;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100328 /* TODO: if needed, add osmo_stats_add_reporter(srep); */
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100329 }
330
331 vty->index = srep;
332 vty->node = CFG_STATS_NODE;
333
334 return CMD_SUCCESS;
335}
336
337DEFUN(cfg_no_stats_reporter_log, cfg_no_stats_reporter_log_cmd,
338 "no stats reporter log",
339 NO_STR CFG_STATS_STR CFG_REPORTER_STR "Report to the logger\n")
340{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100341 struct osmo_stats_reporter *srep;
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100342
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100343 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100344 if (!srep) {
345 vty_out(vty, "%% No log reporting active%s",
346 VTY_NEWLINE);
347 return CMD_WARNING;
348 }
349
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100350 osmo_stats_reporter_free(srep);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100351
352 return CMD_SUCCESS;
353}
354
Alexander Chemeris161adee2020-05-08 18:19:24 +0300355DEFUN(cfg_stats_interval, cfg_stats_interval_cmd,
Daniel Willmann1a1de332020-07-14 18:11:14 +0200356 "stats interval <0-65535>",
Alexander Chemeris161adee2020-05-08 18:19:24 +0300357 CFG_STATS_STR "Set the reporting interval\n"
Daniel Willmann1a1de332020-07-14 18:11:14 +0200358 "Interval in seconds (0 disables the reporting interval)\n")
Alexander Chemeris161adee2020-05-08 18:19:24 +0300359{
360 int rc;
361 int interval = atoi(argv[0]);
362 rc = osmo_stats_set_interval(interval);
363 if (rc < 0) {
364 vty_out(vty, "%% Unable to set interval: %s%s",
365 strerror(-rc), VTY_NEWLINE);
366 return CMD_WARNING;
367 }
368
369 return CMD_SUCCESS;
370}
371
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200372DEFUN(show_stats,
373 show_stats_cmd,
374 "show stats",
375 SHOW_STR SHOW_STATS_STR)
376{
377 vty_out_statistics_full(vty, "");
378
379 return CMD_SUCCESS;
380}
381
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100382DEFUN(show_stats_level,
383 show_stats_level_cmd,
384 "show stats level (global|peer|subscriber)",
385 SHOW_STR SHOW_STATS_STR
Holger Hans Peter Freyther83481942015-11-07 21:10:01 +0100386 "Set the maximum group level\n"
Jacob Erlbeck59b90bc2015-11-03 16:21:40 +0100387 "Show global groups only\n"
388 "Show global and network peer related groups\n"
389 "Show global, peer, and subscriber groups\n")
390{
391 int level = get_string_value(stats_class_strs, argv[0]);
392 vty_out_statistics_partial(vty, "", level);
393
394 return CMD_SUCCESS;
395}
396
Alexander Couzensad580ba2016-05-16 16:01:45 +0200397static int asciidoc_handle_counter(struct osmo_counter *counter, void *sctx_)
398{
399 struct vty *vty = sctx_;
400 char *name = osmo_asciidoc_escape(counter->name);
401 char *description = osmo_asciidoc_escape(counter->description);
402
403 /* | name | This document & | description | */
404 vty_out(vty, "| %s | <<ungroup_counter_%s>> | %s%s",
405 name,
406 name,
407 description ? description : "",
408 VTY_NEWLINE);
409
410 talloc_free(name);
411 talloc_free(description);
412
413 return 0;
414}
415
416static void asciidoc_counter_generate(struct vty *vty)
417{
418 vty_out(vty, "// ungrouped osmo_counters%s", VTY_NEWLINE);
419 vty_out(vty, ".ungrouped osmo counters%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200420 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200421 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200422 vty_out(vty, "| Name | Reference | Description%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200423 osmo_counters_for_each(asciidoc_handle_counter, vty);
424 vty_out(vty, "|===%s", VTY_NEWLINE);
425}
426
427static int asciidoc_rate_ctr_handler(
428 struct rate_ctr_group *ctrg, struct rate_ctr *ctr,
429 const struct rate_ctr_desc *desc, void *sctx_)
430{
431 struct vty *vty = sctx_;
432 char *name = osmo_asciidoc_escape(desc->name);
433 char *description = osmo_asciidoc_escape(desc->description);
434 char *group_name_prefix = osmo_asciidoc_escape(ctrg->desc->group_name_prefix);
435
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200436 /* | Name | This document & | Description | */
Alexander Couzensad580ba2016-05-16 16:01:45 +0200437 vty_out(vty, "| %s | <<%s_%s>> | %s%s",
438 name,
439 group_name_prefix,
440 name,
441 description ? description : NULL,
442 VTY_NEWLINE);
443
444 /* description seems to be optional */
445 talloc_free(name);
446 talloc_free(group_name_prefix);
447 talloc_free(description);
448
449 return 0;
450}
451
452static int asciidoc_rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
453{
454 struct vty *vty = sctx_;
455
456 char *group_description = osmo_asciidoc_escape(ctrg->desc->group_description);
457 char *group_name_prefix = osmo_asciidoc_escape(ctrg->desc->group_name_prefix);
458
459 vty_out(vty, "// rate_ctr_group table %s%s", group_description, VTY_NEWLINE);
Pau Espin Pedrol18e019e2019-06-19 14:24:27 +0200460 vty_out(vty, ".%s - %s%s", group_name_prefix, group_description, VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200461 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200462 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200463 vty_out(vty, "| Name | Reference | Description%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200464 rate_ctr_for_each_counter(ctrg, asciidoc_rate_ctr_handler, sctx_);
465 vty_out(vty, "|===%s", VTY_NEWLINE);
466
467 talloc_free(group_name_prefix);
468 talloc_free(group_description);
469
470 return 0;
471}
472
473static int asciidoc_osmo_stat_item_handler(
474 struct osmo_stat_item_group *statg, struct osmo_stat_item *item, void *sctx_)
475{
476 struct vty *vty = sctx_;
477
Neels Hofmeyre90c7172021-09-14 14:37:38 +0200478 const struct osmo_stat_item_desc *desc = osmo_stat_item_get_desc(item);
479 char *name = osmo_asciidoc_escape(desc->name);
480 char *description = osmo_asciidoc_escape(desc->description);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200481 char *group_name_prefix = osmo_asciidoc_escape(statg->desc->group_name_prefix);
Neels Hofmeyre90c7172021-09-14 14:37:38 +0200482 char *unit = osmo_asciidoc_escape(desc->unit);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200483
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200484 /* | Name | Reference | Description | Unit | */
Alexander Couzensad580ba2016-05-16 16:01:45 +0200485 vty_out(vty, "| %s | <<%s_%s>> | %s | %s%s",
486 name,
487 group_name_prefix,
488 name,
489 description ? description : "",
490 unit ? unit : "",
491 VTY_NEWLINE);
492
493 talloc_free(name);
494 talloc_free(group_name_prefix);
495 talloc_free(description);
496 talloc_free(unit);
497
498 return 0;
499}
500
501static int asciidoc_osmo_stat_item_group_handler(struct osmo_stat_item_group *statg, void *sctx_)
502{
503 char *group_name_prefix = osmo_asciidoc_escape(statg->desc->group_name_prefix);
504 char *group_description = osmo_asciidoc_escape(statg->desc->group_description);
505
506 struct vty *vty = sctx_;
507 vty_out(vty, "%s%s", group_description ? group_description : "" , VTY_NEWLINE);
508
509 vty_out(vty, "// osmo_stat_item_group table %s%s", group_description ? group_description : "", VTY_NEWLINE);
Pau Espin Pedrol18e019e2019-06-19 14:24:27 +0200510 vty_out(vty, ".%s - %s%s", group_name_prefix, group_description ? group_description : "", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200511 vty_out(vty, "[options=\"header\"]%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200512 vty_out(vty, "|===%s", VTY_NEWLINE);
Alexander Couzenseb604cf2016-10-14 13:54:47 +0200513 vty_out(vty, "| Name | Reference | Description | Unit%s", VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200514 osmo_stat_item_for_each_item(statg, asciidoc_osmo_stat_item_handler, sctx_);
515 vty_out(vty, "|===%s", VTY_NEWLINE);
516
517 talloc_free(group_name_prefix);
518 talloc_free(group_description);
519
520 return 0;
521}
522
523DEFUN(show_stats_asciidoc_table,
524 show_stats_asciidoc_table_cmd,
525 "show asciidoc counters",
Harald Weltef624c332016-06-15 11:35:16 +0200526 SHOW_STR "Asciidoc generation\n" "Generate table of all registered counters\n")
Alexander Couzensad580ba2016-05-16 16:01:45 +0200527{
Alexander Couzense052dc22016-10-04 18:04:37 +0200528 vty_out(vty, "// autogenerated by show asciidoc counters%s", VTY_NEWLINE);
Daniel Willmann6f3bbd42019-07-25 11:33:50 +0200529 vty_out(vty, "These counters and their description are based on %s %s (%s).%s%s",
Alexander Couzense052dc22016-10-04 18:04:37 +0200530 host.app_info->name,
531 host.app_info->version,
532 host.app_info->name ? host.app_info->name : "", VTY_NEWLINE, VTY_NEWLINE);
533 /* 2x VTY_NEWLINE are intentional otherwise it would interpret the first table header
534 * as usual text*/
Daniel Willmannd910a352018-07-24 20:01:26 +0200535 vty_out(vty, "=== Rate Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200536 vty_out(vty, "// generating tables for rate_ctr_group%s", VTY_NEWLINE);
537 rate_ctr_for_each_group(asciidoc_rate_ctr_group_handler, vty);
538
Daniel Willmann81588822021-06-16 14:19:48 +0200539 vty_out(vty, "=== Osmo Stat Items%s%s", VTY_NEWLINE, VTY_NEWLINE);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200540 vty_out(vty, "// generating tables for osmo_stat_items%s", VTY_NEWLINE);
541 osmo_stat_item_for_each_group(asciidoc_osmo_stat_item_group_handler, vty);
542
Daniel Willmann81588822021-06-16 14:19:48 +0200543 if (osmo_counters_count() == 0)
544 {
545 vty_out(vty, "// there are no ungrouped osmo_counters%s",
546 VTY_NEWLINE);
547 } else {
548 vty_out(vty, "=== Osmo Counters%s%s", VTY_NEWLINE, VTY_NEWLINE);
549 vty_out(vty, "// generating tables for osmo_counters%s", VTY_NEWLINE);
550 asciidoc_counter_generate(vty);
551 }
Alexander Couzensad580ba2016-05-16 16:01:45 +0200552 return CMD_SUCCESS;
553}
554
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200555static int rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
556{
557 struct vty *vty = sctx_;
Vadim Yanitskiye9fd81a2021-06-06 18:02:57 +0200558 vty_out(vty, "%s %u", ctrg->desc->group_description, ctrg->idx);
559 if (ctrg->name != NULL)
560 vty_out(vty, " (%s)", ctrg->name);
561 vty_out(vty, ":%s", VTY_NEWLINE);
Stefan Sperling73b7fa62018-05-24 18:40:03 +0200562 vty_out_rate_ctr_group_fmt(vty, "%25n: %10c (%S/s %M/m %H/h %D/d) %d", ctrg);
563 return 0;
564}
565
566DEFUN(show_rate_counters,
567 show_rate_counters_cmd,
568 "show rate-counters",
569 SHOW_STR "Show all rate counters\n")
570{
571 rate_ctr_for_each_group(rate_ctr_group_handler, vty);
572 return CMD_SUCCESS;
573}
574
Daniel Willmann1a1de332020-07-14 18:11:14 +0200575DEFUN(stats_report,
576 stats_report_cmd,
577 "stats report",
578 STATS_STR "Manurally trigger reporting of stats\n")
579{
580 osmo_stats_report();
581 return CMD_SUCCESS;
582}
583
584static int reset_rate_ctr_group_handler(struct rate_ctr_group *ctrg, void *sctx_)
585{
586 rate_ctr_group_reset(ctrg);
587 return 0;
588}
589
Daniel Willmann1a1de332020-07-14 18:11:14 +0200590DEFUN(stats_reset,
591 stats_reset_cmd,
592 "stats reset",
Neels Hofmeyr923cb842021-08-20 17:09:38 +0200593 STATS_STR "Reset all rate counter stats\n")
Daniel Willmann1a1de332020-07-14 18:11:14 +0200594{
595 rate_ctr_for_each_group(reset_rate_ctr_group_handler, NULL);
Daniel Willmann1a1de332020-07-14 18:11:14 +0200596 return CMD_SUCCESS;
597}
598
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100599static int config_write_stats_reporter(struct vty *vty, struct osmo_stats_reporter *srep)
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200600{
601 if (srep == NULL)
602 return 0;
603
604 switch (srep->type) {
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100605 case OSMO_STATS_REPORTER_STATSD:
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200606 vty_out(vty, "stats reporter statsd%s", VTY_NEWLINE);
607 break;
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100608 case OSMO_STATS_REPORTER_LOG:
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100609 vty_out(vty, "stats reporter log%s", VTY_NEWLINE);
610 break;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200611 }
612
613 vty_out(vty, " disable%s", VTY_NEWLINE);
614
Jacob Erlbecked197fd2015-10-27 14:43:24 +0100615 if (srep->have_net_config) {
616 if (srep->dest_addr_str)
617 vty_out(vty, " remote-ip %s%s",
618 srep->dest_addr_str, VTY_NEWLINE);
619 if (srep->dest_port)
620 vty_out(vty, " remote-port %d%s",
621 srep->dest_port, VTY_NEWLINE);
622 if (srep->bind_addr_str)
623 vty_out(vty, " local-ip %s%s",
624 srep->bind_addr_str, VTY_NEWLINE);
625 if (srep->mtu)
626 vty_out(vty, " mtu %d%s",
627 srep->mtu, VTY_NEWLINE);
628 }
629
Jacob Erlbeckbc9d9ac2015-11-02 14:49:35 +0100630 if (srep->max_class)
631 vty_out(vty, " level %s%s",
632 get_value_string(stats_class_strs, srep->max_class),
633 VTY_NEWLINE);
634
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200635 if (srep->name_prefix && *srep->name_prefix)
636 vty_out(vty, " prefix %s%s",
637 srep->name_prefix, VTY_NEWLINE);
638 else
639 vty_out(vty, " no prefix%s", VTY_NEWLINE);
640
Alexander Chemerisdfebf402020-05-08 19:10:40 +0300641 if (srep->flush_period > 0)
642 vty_out(vty, " flush-period %d%s",
643 srep->flush_period, VTY_NEWLINE);
644
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200645 if (srep->enabled)
646 vty_out(vty, " enable%s", VTY_NEWLINE);
647
648 return 1;
649}
650
651static int config_write_stats(struct vty *vty)
652{
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100653 struct osmo_stats_reporter *srep;
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200654
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100655 /* TODO: loop through all reporters */
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100656 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_STATSD, NULL);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200657 config_write_stats_reporter(vty, srep);
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100658 srep = osmo_stats_reporter_find(OSMO_STATS_REPORTER_LOG, NULL);
Jacob Erlbeckbc4f7ae2015-10-28 21:47:45 +0100659 config_write_stats_reporter(vty, srep);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200660
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100661 vty_out(vty, "stats interval %d%s", osmo_stats_config->interval, VTY_NEWLINE);
Jacob Erlbeckb1dbfb42015-10-26 11:58:38 +0100662
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200663 return 1;
664}
665
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200666/*! Add stats related commands to the VTY
Harald Welte96e2a002017-06-12 21:44:18 +0200667 * Call this once during your application initialization if you would
668 * like to have stats VTY commands enabled.
669 */
Jacob Erlbeckfc9533d2015-10-29 00:55:58 +0100670void osmo_stats_vty_add_cmds()
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200671{
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700672 install_lib_element_ve(&show_stats_cmd);
673 install_lib_element_ve(&show_stats_level_cmd);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200674
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700675 install_lib_element(CONFIG_NODE, &cfg_stats_reporter_statsd_cmd);
676 install_lib_element(CONFIG_NODE, &cfg_no_stats_reporter_statsd_cmd);
677 install_lib_element(CONFIG_NODE, &cfg_stats_reporter_log_cmd);
678 install_lib_element(CONFIG_NODE, &cfg_no_stats_reporter_log_cmd);
679 install_lib_element(CONFIG_NODE, &cfg_stats_interval_cmd);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200680
681 install_node(&cfg_stats_node, config_write_stats);
Jacob Erlbeckadc900e2015-10-20 19:05:52 +0200682
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700683 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_local_ip_cmd);
684 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_local_ip_cmd);
685 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_ip_cmd);
686 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_remote_port_cmd);
687 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_mtu_cmd);
688 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_mtu_cmd);
689 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_prefix_cmd);
690 install_lib_element(CFG_STATS_NODE, &cfg_no_stats_reporter_prefix_cmd);
691 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_level_cmd);
692 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_enable_cmd);
693 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_disable_cmd);
694 install_lib_element(CFG_STATS_NODE, &cfg_stats_reporter_flush_period_cmd);
Alexander Couzensad580ba2016-05-16 16:01:45 +0200695
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700696 install_lib_element_ve(&show_stats_asciidoc_table_cmd);
697 install_lib_element_ve(&show_rate_counters_cmd);
Daniel Willmann1a1de332020-07-14 18:11:14 +0200698
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +0700699 install_lib_element(ENABLE_NODE, &stats_report_cmd);
700 install_lib_element(ENABLE_NODE, &stats_reset_cmd);
Jacob Erlbeck45513e62015-10-19 15:14:13 +0200701}