Asterisk - The Open Source Telephony Project  18.5.0
bridges.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2019 Sangoma, Inc.
5  *
6  * Matt Jordan <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief Prometheus Bridge Metrics
22  *
23  * \author Matt Jordan <[email protected]>
24  *
25  */
26 
27 #include "asterisk.h"
28 
31 #include "prometheus_internal.h"
32 
33 #define BRIDGES_CHANNELS_COUNT_HELP "Number of channels in the bridge."
34 
35 /*!
36  * \internal
37  * \brief Callback function to get the number of channels in a bridge
38  *
39  * \param metric The metric to populate
40  * \snapshot Bridge snapshot
41  */
42 static void get_bridge_channel_count(struct prometheus_metric *metric, struct ast_bridge_snapshot *snapshot)
43 {
44  snprintf(metric->value, sizeof(metric->value), "%d", snapshot->num_channels);
45 }
46 
47 /*!
48  * \internal
49  * \brief Helper struct for generating individual bridge stats
50  */
52  /*!
53  * \brief Help text to display
54  */
55  const char *help;
56  /*!
57  * \brief Name of the metric
58  */
59  const char *name;
60  /*!
61  * \brief Callback function to generate a metric value for a given bridge
62  */
63  void (* const get_value)(struct prometheus_metric *metric, struct ast_bridge_snapshot *snapshot);
64 } bridge_metric_defs[] = {
65  {
67  .name = "asterisk_bridges_channels_count",
68  .get_value = get_bridge_channel_count,
69  },
70 };
71 
72 /*!
73  * \internal
74  * \brief Callback invoked when Prometheus scrapes the server
75  *
76  * \param response The response to populate with formatted metrics
77  */
78 static void bridges_scrape_cb(struct ast_str **response)
79 {
80  struct ao2_container *bridge_cache;
81  struct ao2_container *bridges;
82  struct ao2_iterator it_bridges;
83  struct ast_bridge *bridge;
84  struct prometheus_metric *bridge_metrics;
85  char eid_str[32];
86  int i, j, num_bridges;
89  "asterisk_bridges_count",
90  "Current bridge count.",
91  NULL
92  );
93 
94  ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
95 
96  bridge_cache = ast_bridges();
97  if (!bridge_cache) {
98  return;
99  }
100 
101  bridges = ao2_container_clone(bridge_cache, 0);
102  ao2_ref(bridge_cache, -1);
103  if (!bridges) {
104  return;
105  }
106 
107  num_bridges = ao2_container_count(bridges);
108 
109  /* Current endpoint count */
110  PROMETHEUS_METRIC_SET_LABEL(&bridge_count, 0, "eid", eid_str);
111  snprintf(bridge_count.value, sizeof(bridge_count.value), "%d", num_bridges);
112  prometheus_metric_to_string(&bridge_count, response);
113 
114  if (num_bridges == 0) {
115  ao2_ref(bridges, -1);
116  return;
117  }
118 
119  bridge_metrics = ast_calloc(ARRAY_LEN(bridge_metric_defs) * num_bridges, sizeof(*bridge_metrics));
120  if (!bridge_metrics) {
121  ao2_ref(bridges, -1);
122  return;
123  }
124 
125  /* Bridge dependent values */
126  it_bridges = ao2_iterator_init(bridges, 0);
127  for (i = 0; (bridge = ao2_iterator_next(&it_bridges)); ao2_ref(bridge, -1), i++) {
128  struct ast_bridge_snapshot *snapshot = ast_bridge_get_snapshot(bridge);
129 
130  for (j = 0; j < ARRAY_LEN(bridge_metric_defs); j++) {
131  int index = i * ARRAY_LEN(bridge_metric_defs) + j;
132 
133  bridge_metrics[index].type = PROMETHEUS_METRIC_GAUGE;
134  ast_copy_string(bridge_metrics[index].name, bridge_metric_defs[j].name, sizeof(bridge_metrics[index].name));
135  bridge_metrics[index].help = bridge_metric_defs[j].help;
136  PROMETHEUS_METRIC_SET_LABEL(&bridge_metrics[index], 0, "eid", eid_str);
137  PROMETHEUS_METRIC_SET_LABEL(&bridge_metrics[index], 1, "id", (snapshot->uniqueid));
138  PROMETHEUS_METRIC_SET_LABEL(&bridge_metrics[index], 2, "tech", (snapshot->technology));
139  PROMETHEUS_METRIC_SET_LABEL(&bridge_metrics[index], 3, "subclass", (snapshot->subclass));
140  PROMETHEUS_METRIC_SET_LABEL(&bridge_metrics[index], 4, "creator", (snapshot->creator));
141  PROMETHEUS_METRIC_SET_LABEL(&bridge_metrics[index], 5, "name", (snapshot->name));
142  bridge_metric_defs[j].get_value(&bridge_metrics[index], snapshot);
143 
144  if (i > 0) {
145  AST_LIST_INSERT_TAIL(&bridge_metrics[j].children, &bridge_metrics[index], entry);
146  }
147  }
148  ao2_ref(snapshot, -1);
149  }
150  ao2_iterator_destroy(&it_bridges);
151 
152  for (j = 0; j < ARRAY_LEN(bridge_metric_defs); j++) {
153  prometheus_metric_to_string(&bridge_metrics[j], response);
154  }
155 
156  ast_free(bridge_metrics);
157  ao2_ref(bridges, -1);
158 }
159 
161  .name = "bridges callback",
162  .callback_fn = bridges_scrape_cb,
163 };
164 
165 /*!
166  * \internal
167  * \brief Callback invoked when the core module is unloaded
168  */
169 static void bridge_metrics_unload_cb(void)
170 {
171  prometheus_callback_unregister(&bridges_callback);
172 }
173 
174 /*!
175  * \internal
176  * \brief Metrics provider definition
177  */
179  .name = "bridges",
180  .unload_cb = bridge_metrics_unload_cb,
181 };
182 
184 {
186  prometheus_callback_register(&bridges_callback);
187 
188  return 0;
189 }
struct ao2_container * ast_bridges(void)
Returns the global bridges container.
Definition: bridge.c:174
struct prometheus_callback bridges_callback
Definition: bridges.c:160
Asterisk main include file. File version handling, generic pbx functions.
An actual, honest to god, metric.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
int prometheus_callback_register(struct prometheus_callback *callback)
#define ao2_container_clone(orig, flags)
Definition: astobj2.h:1430
Structure that contains a snapshot of information about a bridge.
Definition: bridge.h:322
const char * name
The name of our callback (always useful for debugging)
static void bridge_metrics_unload_cb(void)
Definition: bridges.c:169
enum prometheus_metric_type type
What type of metric we are.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define NULL
Definition: resample.c:96
const ast_string_field creator
Definition: bridge.h:336
#define PROMETHEUS_METRIC_STATIC_INITIALIZATION(mtype, n, h, cb)
Convenience macro for initializing a metric on the stack.
void prometheus_metric_to_string(struct prometheus_metric *metric, struct ast_str **output)
Convert a metric (and its children) into Prometheus compatible text.
const ast_string_field technology
Definition: bridge.h:336
#define PROMETHEUS_METRIC_SET_LABEL(metric, label, n, v)
Convenience macro for setting a label / value in a metric.
struct ast_bridge_snapshot * ast_bridge_get_snapshot(struct ast_bridge *bridge)
Returns the current snapshot for the bridge.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void get_bridge_channel_count(struct prometheus_metric *metric, struct ast_bridge_snapshot *snapshot)
Definition: bridges.c:42
void prometheus_metrics_provider_register(const struct prometheus_metrics_provider *provider)
Register a metrics provider.
Structure that contains information about a bridge.
Definition: bridge.h:357
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const ast_string_field name
Definition: bridge.h:336
#define BRIDGES_CHANNELS_COUNT_HELP
Definition: bridges.c:33
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
char value[PROMETHEUS_MAX_VALUE_LENGTH]
The current value.
static struct ao2_container * bridges
Definition: bridge.c:123
const char * help
Pointer to a static string defining this metric&#39;s help text.
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
const ast_string_field uniqueid
Definition: bridge.h:336
void prometheus_callback_unregister(struct prometheus_callback *callback)
Remove a registered callback.
unsigned int num_channels
Definition: bridge.h:345
const char * name
Handy name of the provider for debugging purposes.
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
A function table for a metrics provider.
static void bridges_scrape_cb(struct ast_str **response)
Definition: bridges.c:78
const char * name
Name of the metric.
Definition: bridges.c:59
Definition: search.h:40
Generic container type.
const char * help
Help text to display.
Definition: bridges.c:55
const ast_string_field subclass
Definition: bridge.h:336
static struct prometheus_metrics_provider provider
Definition: bridges.c:178
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
Defines a callback that will be invoked when the HTTP route is called.
void(*const get_value)(struct prometheus_metric *metric, struct ast_bridge_snapshot *snapshot)
Callback function to generate a metric value for a given bridge.
Definition: bridges.c:63
int bridge_metrics_init(void)
Initialize bridge metrics.
Definition: bridges.c:183