Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Functions | Variables
pjsip_outbound_registrations.c File Reference

Prometheus PJSIP Outbound Registration Metrics. More...

#include "asterisk.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/stasis_system.h"
#include "asterisk/res_prometheus.h"
#include "asterisk/res_pjsip.h"
#include "prometheus_internal.h"
Include dependency graph for pjsip_outbound_registrations.c:

Go to the source code of this file.

Data Structures

struct  prometheus_metric_wrapper
 

Functions

static AST_VECTOR (struct prometheus_metric_wrapper *)
 
static struct prometheus_metric_wrapperget_wrapper (const char *key)
 
int pjsip_outbound_registration_metrics_init (void)
 Initialize PJSIP outbound registration metrics. More...
 
static void pjsip_outbound_registration_metrics_unload_cb (void)
 
static void registration_deleted_observer (const void *obj)
 
static void registration_loaded_observer (const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
 
static int registration_state_to_int (const char *state)
 
static void registry_message_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 

Variables

static ast_mutex_t metrics_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
 
static struct prometheus_metrics_provider provider
 
static const struct ast_sorcery_observer registration_observer
 
static struct stasis_message_routerrouter
 

Detailed Description

Prometheus PJSIP Outbound Registration Metrics.

Author
Matt Jordan mjord[email protected][email protected][email protected]igium[email protected].com

Definition in file pjsip_outbound_registrations.c.

Function Documentation

◆ AST_VECTOR()

static AST_VECTOR ( struct prometheus_metric_wrapper )
static

Definition at line 78 of file pjsip_outbound_registrations.c.

References ast_calloc, ast_copy_string(), prometheus_metric_wrapper::key, and NULL.

90 {
91  struct prometheus_metric_wrapper *wrapper;
92 
93  wrapper = ast_calloc(1, sizeof(*wrapper));
94  if (!wrapper) {
95  return NULL;
96  }
97 
98  ast_copy_string(wrapper->key, key, sizeof(wrapper->key));
99  return wrapper;
100 }
#define NULL
Definition: resample.c:96
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char key[128]
Unique key to look up the metric.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401

◆ get_wrapper()

static struct prometheus_metric_wrapper* get_wrapper ( const char *  key)
static

Definition at line 111 of file pjsip_outbound_registrations.c.

References AST_VECTOR_GET, AST_VECTOR_SIZE, prometheus_metric_wrapper::key, lock, metrics_lock, NULL, and SCOPED_MUTEX.

Referenced by registry_message_cb().

112 {
113  int i;
115 
116  for (i = 0; i < AST_VECTOR_SIZE(&metrics); i++) {
117  struct prometheus_metric_wrapper *wrapper = AST_VECTOR_GET(&metrics, i);
118 
119  if (!strcmp(wrapper->key, key)) {
120  return wrapper;
121  }
122  }
123 
124  return NULL;
125 }
#define NULL
Definition: resample.c:96
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition: lock.h:587
ast_mutex_t lock
Definition: app_meetme.c:1091
char key[128]
Unique key to look up the metric.
static ast_mutex_t metrics_lock
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ pjsip_outbound_registration_metrics_init()

int pjsip_outbound_registration_metrics_init ( void  )

Initialize PJSIP outbound registration metrics.

Return values
0success
-1error

Definition at line 342 of file pjsip_outbound_registrations.c.

References ao2_cleanup, ast_sip_get_sorcery(), ast_sorcery_instance_observer_add(), ast_sorcery_instance_observer_remove(), ast_sorcery_observer_add(), ast_sorcery_observer_remove(), ast_system_registry_type(), ast_system_topic(), cleanup(), NULL, prometheus_metrics_provider_register(), registry_message_cb(), stasis_message_router_add(), and stasis_message_router_create.

Referenced by load_module().

343 {
345 
346 #ifdef HAVE_PJPROJECT
348  if (!router) {
349  goto cleanup;
350  }
351 
353  goto cleanup;
354  }
355 
357  goto cleanup;
358  }
359 
361  goto cleanup;
362  }
363 #endif /* HAVE_PJPROJECT */
364  return 0;
365 
366 #ifdef HAVE_PJPROJECT
367 cleanup:
369  router = NULL;
372 
373  return -1;
374 #endif /* HAVE_PJPROJECT */
375 }
int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Add an observer to a sorcery instance.
Definition: sorcery.c:520
static struct stasis_message_router * router
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
static void registry_message_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
#define NULL
Definition: resample.c:96
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
static const struct ast_sorcery_observer registration_observer
void prometheus_metrics_provider_register(const struct prometheus_metrics_provider *provider)
Register a metrics provider.
#define stasis_message_router_create(topic)
void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Remove an observer from a sorcery instance.
Definition: sorcery.c:537
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2386
struct stasis_message_type * ast_system_registry_type(void)
A stasis_message_type for outbound registration.
struct stasis_topic * ast_system_topic(void)
A Stasis Message Bus API topic which publishes messages regarding system changes. ...
static void * cleanup(void *unused)
Definition: pbx_realtime.c:124
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2418
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct prometheus_metrics_provider provider

◆ pjsip_outbound_registration_metrics_unload_cb()

static void pjsip_outbound_registration_metrics_unload_cb ( void  )
static

Definition at line 323 of file pjsip_outbound_registrations.c.

References ast_sip_get_sorcery(), ast_sorcery_instance_observer_remove(), ast_sorcery_observer_remove(), NULL, and stasis_message_router_unsubscribe_and_join().

324 {
325 #ifdef HAVE_PJPROJECT
327  router = NULL;
330 #endif /* HAVE_PJPROJECT */
331 }
static struct stasis_message_router * router
void stasis_message_router_unsubscribe_and_join(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic, blocking until the final message has been processed...
#define NULL
Definition: resample.c:96
static const struct ast_sorcery_instance_observer observer_callbacks_registrations
static const struct ast_sorcery_observer registration_observer
void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Remove an observer from a sorcery instance.
Definition: sorcery.c:537
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2418
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.

◆ registration_deleted_observer()

static void registration_deleted_observer ( const void *  obj)
static

Definition at line 151 of file pjsip_outbound_registrations.c.

References ast_debug, ast_free, ast_sip_get_sorcery(), ast_sorcery_objectset_create, ast_variables_destroy(), AST_VECTOR_GET, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, prometheus_metric_wrapper::key, lock, prometheus_metric_wrapper::metric, metrics_lock, ast_variable::name, ast_variable::next, prometheus_metric_unregister(), SCOPED_MUTEX, and ast_variable::value.

152 {
153  struct ast_variable *fields;
154  struct ast_variable *it_fields;
155  int i;
157 
158  /*
159  * Because our object is opaque, we have to do some pretty ... interesting
160  * things here to try and figure out what just happened.
161  */
163  if (!fields) {
164  ast_debug(1, "Unable to convert presumed registry object %p to strings; bailing on delete\n", obj);
165  return;
166  }
167 
168  for (it_fields = fields; it_fields; it_fields = it_fields->next) {
169  if (strcasecmp(it_fields->name, "client_uri")) {
170  continue;
171  }
172 
173  for (i = 0; i < AST_VECTOR_SIZE(&metrics); i++) {
174  struct prometheus_metric_wrapper *wrapper = AST_VECTOR_GET(&metrics, i);
175 
176  if (strcmp(wrapper->key, it_fields->value)) {
177  continue;
178  }
179 
180  ast_debug(1, "Registration metric '%s' deleted; purging with prejudice\n", wrapper->key);
181  AST_VECTOR_REMOVE(&metrics, i, 1);
182  /* This will free the metric as well */
184  ast_free(wrapper);
185  }
186  }
187 
188  ast_variables_destroy(fields);
189 }
struct ast_variable * next
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
struct prometheus_metric * metric
The actual metric. Worth noting that we do NOT own the metric, as it is registered with res_prometheu...
Structure for variables, used for configurations and for channel variables.
int prometheus_metric_unregister(struct prometheus_metric *metric)
Remove a registered metric.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition: lock.h:587
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition: sorcery.h:1136
#define ast_free(a)
Definition: astmm.h:182
char key[128]
Unique key to look up the metric.
static ast_mutex_t metrics_lock
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ registration_loaded_observer()

static void registration_loaded_observer ( const char *  name,
const struct ast_sorcery sorcery,
const char *  object_type,
int  reloaded 
)
static

Definition at line 212 of file pjsip_outbound_registrations.c.

References ao2_ref, ast_debug, ast_free, AST_RETRIEVE_FLAG_DEFAULT, ast_sip_get_sorcery(), ast_sorcery_retrieve_by_fields(), AST_VECTOR_GET, AST_VECTOR_REMOVE, AST_VECTOR_SIZE, prometheus_metric_wrapper::key, lock, prometheus_metric_wrapper::metric, metrics_lock, ast_variable::name, NULL, prometheus_metric_unregister(), and SCOPED_MUTEX.

213 {
215  int i;
216 
217  if (!reloaded) {
218  /* Meh */
219  return;
220  }
221 
222  if (strcmp(object_type, "registration")) {
223  /* Not interested */
224  return;
225  }
226 
227  for (i = 0; i < AST_VECTOR_SIZE(&metrics); i++) {
228  struct prometheus_metric_wrapper *wrapper = AST_VECTOR_GET(&metrics, i);
229  struct ast_variable search_fields = {
230  .name = "client_uri",
231  .value = wrapper->key,
232  .next = NULL,
233  };
234  void *obj;
235 
236  ast_debug(1, "Checking for the existance of registration metric %s\n", wrapper->key);
238  if (!obj) {
239  ast_debug(1, "Registration metric '%s' not found; purging with prejudice\n", wrapper->key);
240  AST_VECTOR_REMOVE(&metrics, i, 1);
241  /* This will free the metric as well */
243  ast_free(wrapper);
244  continue;
245  }
246  ao2_ref(obj, -1);
247  }
248 
249 }
struct prometheus_metric * metric
The actual metric. Worth noting that we do NOT own the metric, as it is registered with res_prometheu...
Structure for variables, used for configurations and for channel variables.
int prometheus_metric_unregister(struct prometheus_metric *metric)
Remove a registered metric.
#define NULL
Definition: resample.c:96
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition: lock.h:587
ast_mutex_t lock
Definition: app_meetme.c:1091
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Default retrieval flags.
Definition: sorcery.h:117
#define ast_free(a)
Definition: astmm.h:182
char key[128]
Unique key to look up the metric.
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1897
static ast_mutex_t metrics_lock
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:682
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
Definition: vector.h:412
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:611

◆ registration_state_to_int()

static int registration_state_to_int ( const char *  state)
static

Definition at line 135 of file pjsip_outbound_registrations.c.

Referenced by registry_message_cb().

136 {
137  if (!strcasecmp(state, "Registered")) {
138  return 1;
139  } else if (!strcasecmp(state, "Rejected")) {
140  return 2;
141  }
142  return 0;
143 }

◆ registry_message_cb()

static void registry_message_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 267 of file pjsip_outbound_registrations.c.

References ast_eid_default, ast_eid_to_str(), ast_free, ast_json_object_get(), ast_json_string_get(), ast_mutex_lock, ast_mutex_unlock, AST_VECTOR_APPEND, channel_type, get_wrapper(), prometheus_metric::help, ast_json_payload::json, prometheus_metric::lock, prometheus_metric_wrapper::metric, prometheus_metric::name, NULL, prometheus_gauge_create(), PROMETHEUS_METRIC_GAUGE, prometheus_metric_register(), PROMETHEUS_METRIC_SET_LABEL, PROMETHEUS_METRIC_STATIC_INITIALIZATION, registration_state_to_int(), stasis_message_data(), and prometheus_metric::value.

Referenced by pjsip_outbound_registration_metrics_init().

269 {
270  struct ast_json_payload *payload = stasis_message_data(message);
271  struct ast_json *json = payload->json;
272  const char *username = ast_json_string_get(ast_json_object_get(json, "username"));
273  const char *status_str = ast_json_string_get(ast_json_object_get(json, "status"));
274  const char *domain = ast_json_string_get(ast_json_object_get(json, "domain"));
275  const char *channel_type = ast_json_string_get(ast_json_object_get(json, "channeltype"));
278  "asterisk_pjsip_outbound_registration_status",
279  "Current registration status. 0=Unregistered; 1=Registered; 2=Rejected.",
280  NULL
281  );
282  struct prometheus_metric_wrapper *wrapper;
283  char eid_str[32];
284 
285  ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
286 
287  PROMETHEUS_METRIC_SET_LABEL(&metric, 0, "eid", eid_str);
288  PROMETHEUS_METRIC_SET_LABEL(&metric, 1, "username", username);
289  PROMETHEUS_METRIC_SET_LABEL(&metric, 2, "domain", domain);
290  PROMETHEUS_METRIC_SET_LABEL(&metric, 3, "channel_type", channel_type);
291  snprintf(metric.value, sizeof(metric.value), "%d", registration_state_to_int(status_str));
292 
293  wrapper = get_wrapper(username);
294  if (wrapper) {
295  ast_mutex_lock(&wrapper->metric->lock);
296  /* Safe */
297  strcpy(wrapper->metric->value, metric.value);
298  ast_mutex_unlock(&wrapper->metric->lock);
299  } else {
300  wrapper = create_wrapper(username);
301  if (!wrapper) {
302  return;
303  }
304 
305  wrapper->metric = prometheus_gauge_create(metric.name, metric.help);
306  if (!wrapper->metric) {
307  ast_free(wrapper);
308  return;
309  }
310  *(wrapper->metric) = metric;
311 
313  AST_VECTOR_APPEND(&metrics, wrapper);
314  }
315 }
An actual, honest to god, metric.
int prometheus_metric_register(struct prometheus_metric *metric)
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: main/utils.c:2587
struct prometheus_metric * metric
The actual metric. Worth noting that we do NOT own the metric, as it is registered with res_prometheu...
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
struct ast_json * json
Definition: json.h:1025
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
#define PROMETHEUS_METRIC_STATIC_INITIALIZATION(mtype, n, h, cb)
Convenience macro for initializing a metric on the stack.
#define PROMETHEUS_METRIC_SET_LABEL(metric, label, n, v)
Convenience macro for setting a label / value in a metric.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:273
struct prometheus_metric * prometheus_gauge_create(const char *name, const char *help)
Create a malloc&#39;d gauge metric.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
char value[PROMETHEUS_MAX_VALUE_LENGTH]
The current value.
const char * help
Pointer to a static string defining this metric&#39;s help text.
#define ast_free(a)
Definition: astmm.h:182
static int registration_state_to_int(const char *state)
static struct prometheus_metric_wrapper * get_wrapper(const char *key)
char name[PROMETHEUS_MAX_NAME_LENGTH]
Our metric name.
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:397
ast_mutex_t lock
A lock protecting the metric value.
static const char channel_type[]
Definition: chan_motif.c:321
Abstract JSON element (object, array, string, int, ...).
#define ast_mutex_unlock(a)
Definition: lock.h:188

Variable Documentation

◆ metrics_lock

ast_mutex_t metrics_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

◆ observer_callbacks_registrations

const struct ast_sorcery_instance_observer observer_callbacks_registrations
static
Initial value:
= {
.object_type_loaded = registration_loaded_observer,
}
static void registration_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)

Definition at line 251 of file pjsip_outbound_registrations.c.

◆ provider

struct prometheus_metrics_provider provider
static
Initial value:
= {
.name = "pjsip_outbound_registration",
}
static void pjsip_outbound_registration_metrics_unload_cb(void)

Definition at line 337 of file pjsip_outbound_registrations.c.

◆ registration_observer

const struct ast_sorcery_observer registration_observer
static
Initial value:
= {
}
static void registration_deleted_observer(const void *obj)

Definition at line 191 of file pjsip_outbound_registrations.c.

◆ router

struct stasis_message_router* router
static