Asterisk - The Open Source Telephony Project GIT-master-2de1a68
res/prometheus/endpoints.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 <mjordan@digium.com>
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 Endpoint Metrics
22 *
23 * \author Matt Jordan <mjordan@digium.com>
24 *
25 */
26
27#include "asterisk.h"
28
31#include "prometheus_internal.h"
32
33#define ENDPOINTS_STATE_HELP "Individual endpoint states. 0=unknown; 1=offline; 2=online."
34
35#define ENDPOINTS_CHANNELS_COUNT_HELP "Count of the number of channels currently existing that are associated with the endpoint."
36
37/*!
38 * \internal
39 * \brief Callback function to get an endpoint's current state
40 *
41 * \param metric The metric to populate
42 * \param snapshot Endpoint snapshot
43 */
44static void get_endpoint_state(struct prometheus_metric *metric, struct ast_endpoint_snapshot *snapshot)
45{
46 snprintf(metric->value, sizeof(metric->value), "%d", snapshot->state);
47}
48
49/*!
50 * \internal
51 * \brief Callback function to get the current number of channel's associated with an endpoint
52 *
53 * \param metric The metric to populate
54 * \param snapshot Endpoint snapshot
55 */
56static void get_endpoint_channel_count(struct prometheus_metric *metric, struct ast_endpoint_snapshot *snapshot)
57{
58 snprintf(metric->value, sizeof(metric->value), "%d", snapshot->num_channels);
59}
60
61/*!
62 * \internal
63 * \brief Helper struct for generating individual endpoint stats
64 */
66 /*!
67 * \brief Help text to display
68 */
69 const char *help;
70 /*!
71 * \brief Name of the metric
72 */
73 const char *name;
74 /*!
75 * \brief Callback function to generate a metric value for a given endpoint
76 */
77 void (* const get_value)(struct prometheus_metric *metric, struct ast_endpoint_snapshot *snapshot);
79 {
81 .name = "asterisk_endpoints_state",
82 .get_value = get_endpoint_state,
83 },
84 {
86 .name = "asterisk_endpoints_channels_count",
87 .get_value = get_endpoint_channel_count,
88 },
89};
90
91/*!
92 * \internal
93 * \brief Callback invoked when Prometheus scrapes the server
94 *
95 * \param response The response to populate with formatted metrics
96 */
97static void endpoints_scrape_cb(struct ast_str **response)
98{
99 struct ao2_container *endpoint_cache;
100 struct ao2_container *endpoints;
101 struct ao2_iterator it_endpoints;
102 struct stasis_message *message;
103 struct prometheus_metric *endpoint_metrics;
104 char eid_str[32];
105 int i, j, num_endpoints;
108 "asterisk_endpoints_count",
109 "Current endpoint count.",
110 NULL
111 );
112
113 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
114
116 if (!endpoint_cache) {
117 return;
118 }
119 endpoints = ao2_container_clone(endpoint_cache, 0);
120 ao2_ref(endpoint_cache, -1);
121 if (!endpoints) {
122 return;
123 }
124
125 num_endpoints = ao2_container_count(endpoints);
126
127 /* Current endpoint count */
128 PROMETHEUS_METRIC_SET_LABEL(&endpoint_count, 0, "eid", eid_str);
129 snprintf(endpoint_count.value, sizeof(endpoint_count.value), "%d", num_endpoints);
130 prometheus_metric_to_string(&endpoint_count, response);
131
132 if (num_endpoints == 0) {
133 ao2_ref(endpoints, -1);
134 return;
135 }
136
137 endpoint_metrics = ast_calloc(ARRAY_LEN(endpoint_metric_defs) * num_endpoints, sizeof(*endpoint_metrics));
138 if (!endpoint_metrics) {
139 ao2_ref(endpoints, -1);
140 return;
141 }
142
143 /* Endpoint dependent values */
144 it_endpoints = ao2_iterator_init(endpoints, 0);
145 for (i = 0; (message = ao2_iterator_next(&it_endpoints)); ao2_ref(message, -1), i++) {
147
148 for (j = 0; j < ARRAY_LEN(endpoint_metric_defs); j++) {
149 int index = i * ARRAY_LEN(endpoint_metric_defs) + j;
150
151 endpoint_metrics[index].type = PROMETHEUS_METRIC_GAUGE;
152 ast_copy_string(endpoint_metrics[index].name, endpoint_metric_defs[j].name, sizeof(endpoint_metrics[index].name));
153 endpoint_metrics[index].help = endpoint_metric_defs[j].help;
154 PROMETHEUS_METRIC_SET_LABEL(&endpoint_metrics[index], 0, "eid", eid_str);
155 PROMETHEUS_METRIC_SET_LABEL(&endpoint_metrics[index], 1, "id", (snapshot->id));
156 PROMETHEUS_METRIC_SET_LABEL(&endpoint_metrics[index], 2, "tech", (snapshot->tech));
157 PROMETHEUS_METRIC_SET_LABEL(&endpoint_metrics[index], 3, "resource", (snapshot->resource));
158 endpoint_metric_defs[j].get_value(&endpoint_metrics[index], snapshot);
159
160 if (i != 0) {
161 AST_LIST_INSERT_TAIL(&endpoint_metrics[j].children, &endpoint_metrics[index], entry);
162 }
163 }
164 }
165 ao2_iterator_destroy(&it_endpoints);
166
167 for (j = 0; j < ARRAY_LEN(endpoint_metric_defs); j++) {
168 prometheus_metric_to_string(&endpoint_metrics[j], response);
169 }
170
171 ast_free(endpoint_metrics);
172 ao2_ref(endpoints, -1);
173}
174
176 .name = "Endpoints callback",
177 .callback_fn = endpoints_scrape_cb,
178};
179
180/*!
181 * \internal
182 * \brief Callback invoked when the core module is unloaded
183 */
185{
187}
188
189/*!
190 * \internal
191 * \brief Metrics provider definition
192 */
194 .name = "endpoints",
195 .unload_cb = endpoint_metrics_unload_cb,
196};
197
199{
202
203 return 0;
204}
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 const char name[]
Definition: format_mp3.c:68
struct stasis_message_type * ast_endpoint_snapshot_type(void)
Message type for ast_endpoint_snapshot.
struct stasis_cache * ast_endpoint_cache(void)
Backend cache for ast_endpoint_topic_all_cached().
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
static struct ao2_container * endpoints
Prometheus Metric Internal API.
static void endpoint_metrics_unload_cb(void)
static void get_endpoint_channel_count(struct prometheus_metric *metric, struct ast_endpoint_snapshot *snapshot)
struct prometheus_callback endpoints_callback
static void get_endpoint_state(struct prometheus_metric *metric, struct ast_endpoint_snapshot *snapshot)
static struct prometheus_metrics_provider provider
static void endpoints_scrape_cb(struct ast_str **response)
#define ENDPOINTS_CHANNELS_COUNT_HELP
#define ENDPOINTS_STATE_HELP
int endpoint_metrics_init(void)
Initialize endpoint metrics.
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.
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
struct ao2_container * stasis_cache_dump(struct stasis_cache *cache, struct stasis_message_type *type)
Dump cached items to a subscription for the ast_eid_default entity.
Definition: stasis_cache.c:736
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
Endpoint abstractions.
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
A snapshot of an endpoint's state.
const ast_string_field tech
enum ast_endpoint_state state
const ast_string_field id
const ast_string_field resource
Support for dynamic strings.
Definition: strings.h:623
void(*const get_value)(struct prometheus_metric *metric, struct ast_endpoint_snapshot *snapshot)
Callback function to generate a metric value for a given endpoint.
const char * name
Name of the metric.
const char * help
Help text to display.
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.
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.
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