Asterisk - The Open Source Telephony Project GIT-master-2de1a68
channels.c
Go to the documentation of this file.
1
2/*
3 * Asterisk -- An open source telephony toolkit.
4 *
5 * Copyright (C) 2019 Sangoma, Inc.
6 *
7 * Matt Jordan <mjordan@digium.com>
8 *
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
14 *
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
18 */
19
20/*!
21 * \file
22 * \brief Prometheus Channel Metrics
23 *
24 * \author Matt Jordan <mjordan@digium.com>
25 *
26 */
27
28#include "asterisk.h"
31#include "asterisk/pbx.h"
32#include "prometheus_internal.h"
33
34#define CHANNELS_STATE_HELP "Individual channel states. 0=down; 1=reserved; 2=offhook; 3=dialing; 4=ring; 5=ringing; 6=up; 7=busy; 8=dialing_offhook; 9=prering."
35
36#define CHANNELS_DURATION_HELP "Individual channel durations (in seconds)."
37
38/*!
39 * \internal
40 * \brief Callback function to get a channel's current state
41 *
42 * \param metric The metric to populate
43 * \param snapshot Channel snapshot
44 */
45static void get_channel_state(struct prometheus_metric *metric, struct ast_channel_snapshot *snapshot)
46{
47 snprintf(metric->value, sizeof(metric->value), "%d", snapshot->state);
48}
49
50/*!
51 * \internal
52 * \brief Callback function to get a channel's current duration
53 *
54 * \param metric The metric to populate
55 * \param snapshot Channel snapshot
56 */
57static void get_channel_duration(struct prometheus_metric *metric, struct ast_channel_snapshot *snapshot)
58{
59 struct timeval now = ast_tvnow();
60 int64_t duration = ast_tvdiff_sec(now, snapshot->base->creationtime);
61
62 snprintf(metric->value, sizeof(metric->value), "%" PRIu64, duration);
63}
64
65/*!
66 * \internal
67 * \brief Helper struct for generating individual channel stats
68 */
70 /*!
71 * \brief Help text to display
72 */
73 const char *help;
74 /*!
75 * \brief Name of the metric
76 */
77 const char *name;
78 /*!
79 * \brief Callback function to generate a metric value for a given channel
80 */
81 void (* const get_value)(struct prometheus_metric *metric, struct ast_channel_snapshot *snapshot);
83 {
85 .name = "asterisk_channels_state",
86 .get_value = get_channel_state,
87 },
88 {
90 .name = "asterisk_channels_duration_seconds",
91 .get_value = get_channel_duration,
92 },
93};
94
95static void get_total_call_count(struct prometheus_metric *metric)
96{
97 snprintf(metric->value, sizeof(metric->value), "%d", ast_processed_calls());
98}
99
100static void get_current_call_count(struct prometheus_metric *metric)
101{
102 snprintf(metric->value, sizeof(metric->value), "%d", ast_active_calls());
103}
104
105/*!
106 * \internal
107 * \brief Channel based metrics that are always available
108 */
112 "asterisk_calls_sum",
113 "Total call count.",
115 ),
118 "asterisk_calls_count",
119 "Current call count.",
121 ),
122};
123
124/*!
125 * \internal
126 * \brief Callback invoked when Prometheus scrapes the server
127 *
128 * \param response The response to populate with formatted metrics
129 */
130static void channels_scrape_cb(struct ast_str **response)
131{
133 struct ao2_container *channels;
134 struct ao2_iterator it_chans;
135 struct ast_channel_snapshot *snapshot;
136 struct prometheus_metric *channel_metrics;
137 char eid_str[32];
138 int num_channels;
139 int i, j;
142 "asterisk_channels_count",
143 "Current channel count.",
144 NULL
145 );
146
147 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
148
150 if (!channel_cache) {
151 return;
152 }
153
156 if (!channels) {
157 return;
158 }
159
160 num_channels = ao2_container_count(channels);
161
162 /* Channel count */
163 PROMETHEUS_METRIC_SET_LABEL(&channel_count, 0, "eid", eid_str);
164 snprintf(channel_count.value, sizeof(channel_count.value), "%d", num_channels);
165 prometheus_metric_to_string(&channel_count, response);
166
167 /* Global call values */
168 for (i = 0; i < ARRAY_LEN(global_channel_metrics); i++) {
172 }
173
174 if (num_channels == 0) {
175 ao2_ref(channels, -1);
176 return;
177 }
178
179 /* Channel dependent values */
180 channel_metrics = ast_calloc(ARRAY_LEN(channel_metric_defs) * num_channels, sizeof(*channel_metrics));
181 if (!channel_metrics) {
182 ao2_ref(channels, -1);
183 return;
184 }
185
186 it_chans = ao2_iterator_init(channels, 0);
187 for (i = 0; (snapshot = ao2_iterator_next(&it_chans)); ao2_ref(snapshot, -1), i++) {
188 for (j = 0; j < ARRAY_LEN(channel_metric_defs); j++) {
189 int index = i * ARRAY_LEN(channel_metric_defs) + j;
190
191 channel_metrics[index].type = PROMETHEUS_METRIC_GAUGE;
192 ast_copy_string(channel_metrics[index].name, channel_metric_defs[j].name, sizeof(channel_metrics[index].name));
193 channel_metrics[index].help = channel_metric_defs[j].help;
194 PROMETHEUS_METRIC_SET_LABEL(&channel_metrics[index], 0, "eid", eid_str);
195 PROMETHEUS_METRIC_SET_LABEL(&channel_metrics[index], 1, "name", (snapshot->base->name));
196 PROMETHEUS_METRIC_SET_LABEL(&channel_metrics[index], 2, "id", (snapshot->base->uniqueid));
197 PROMETHEUS_METRIC_SET_LABEL(&channel_metrics[index], 3, "type", (snapshot->base->type));
198 if (snapshot->peer) {
199 PROMETHEUS_METRIC_SET_LABEL(&channel_metrics[index], 4, "linkedid", (snapshot->peer->linkedid));
200 }
201 channel_metric_defs[j].get_value(&channel_metrics[index], snapshot);
202
203 if (i > 0) {
204 AST_LIST_INSERT_TAIL(&channel_metrics[j].children, &channel_metrics[index], entry);
205 }
206 }
207 }
208 ao2_iterator_destroy(&it_chans);
209
210 for (j = 0; j < ARRAY_LEN(channel_metric_defs); j++) {
211 prometheus_metric_to_string(&channel_metrics[j], response);
212 }
213
214 ast_free(channel_metrics);
215 ao2_ref(channels, -1);
216}
217
219 .name = "Channels callback",
220 .callback_fn = channels_scrape_cb,
221};
222
223/*!
224 * \internal
225 * \brief Callback invoked when the core module is unloaded
226 */
228{
230}
231
232/*!
233 * \internal
234 * \brief Metrics provider definition
235 */
237 .name = "channels",
238 .unload_cb = channel_metrics_unload_cb,
239};
240
242{
245
246 return 0;
247}
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_container_clone(orig, flags)
Create a clone/copy of the given container.
Definition: astobj2.h:1419
static void channel_metrics_unload_cb(void)
Definition: channels.c:227
static void get_current_call_count(struct prometheus_metric *metric)
Definition: channels.c:100
int channel_metrics_init(void)
Initialize channel metrics.
Definition: channels.c:241
#define CHANNELS_DURATION_HELP
Definition: channels.c:36
static void get_channel_state(struct prometheus_metric *metric, struct ast_channel_snapshot *snapshot)
Definition: channels.c:45
static void get_channel_duration(struct prometheus_metric *metric, struct ast_channel_snapshot *snapshot)
Definition: channels.c:57
#define CHANNELS_STATE_HELP
Definition: channels.c:34
static struct prometheus_metrics_provider provider
Definition: channels.c:236
static void get_total_call_count(struct prometheus_metric *metric)
Definition: channels.c:95
static struct prometheus_metric global_channel_metrics[]
Definition: channels.c:109
static void channels_scrape_cb(struct ast_str **response)
Definition: channels.c:130
struct prometheus_callback channels_callback
Definition: channels.c:218
static struct channel_usage channels
static const char name[]
Definition: format_mp3.c:68
struct ao2_container * ast_channel_cache_all(void)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
Core PBX routines and definitions.
int ast_active_calls(void)
Retrieve the number of active calls.
Definition: pbx.c:4760
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
Definition: pbx.c:4765
Prometheus Metric Internal API.
Asterisk Prometheus Metrics.
#define PROMETHEUS_METRIC_SET_LABEL(metric, label, n, v)
Convenience macro for setting a label / value in a metric.
#define PROMETHEUS_METRIC_STATIC_INITIALIZATION(mtype, n, h, cb)
Convenience macro for initializing a metric on the stack.
@ PROMETHEUS_METRIC_GAUGE
A metric whose value can bounce around like a jackrabbit.
@ PROMETHEUS_METRIC_COUNTER
A metric whose value always goes up.
void prometheus_callback_unregister(struct prometheus_callback *callback)
Remove a registered callback.
void prometheus_metric_to_string(struct prometheus_metric *metric, struct ast_str **output)
Convert a metric (and its children) into Prometheus compatible text.
void prometheus_metrics_provider_register(const struct prometheus_metrics_provider *provider)
Register a metrics provider.
int prometheus_callback_register(struct prometheus_callback *callback)
#define NULL
Definition: resample.c:96
static struct ao2_container * channel_cache
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
const ast_string_field uniqueid
const ast_string_field type
const ast_string_field name
Structure representing a snapshot of channel state.
struct ast_channel_snapshot_peer * peer
struct ast_channel_snapshot_base * base
enum ast_channel_state state
Support for dynamic strings.
Definition: strings.h:623
void(*const get_value)(struct prometheus_metric *metric, struct ast_channel_snapshot *snapshot)
Callback function to generate a metric value for a given channel.
Definition: channels.c:81
const char * name
Name of the metric.
Definition: channels.c:77
const char * help
Help text to display.
Definition: channels.c:73
Definition: search.h:40
Defines a callback that will be invoked when the HTTP route is called.
const char * name
The name of our callback (always useful for debugging)
An actual, honest to god, metric.
struct prometheus_metric::@270 children
A list of children metrics.
void(* get_metric_value)(struct prometheus_metric *metric)
Callback function to obtain the metric value.
const char * help
Pointer to a static string defining this metric's help text.
char value[PROMETHEUS_MAX_VALUE_LENGTH]
The current value.
enum prometheus_metric_type type
What type of metric we are.
A function table for a metrics provider.
const char * name
Handy name of the provider for debugging purposes.
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
Definition: time.h:73
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839
#define ARRAY_LEN(a)
Definition: utils.h:666
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93