36#include "../res/prometheus/prometheus_internal.h" 
   38#define CATEGORY "/res/prometheus/" 
   50    curl_easy_cleanup(ptr);
 
 
   72    config->core_metrics_enabled = 0;
 
 
   81    curl = curl_easy_init();
 
   86    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
 
   87    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180L);
 
   89    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
 
   90    curl_easy_setopt(curl, CURLOPT_URL, 
server_uri);
 
 
   97    struct ast_str **buffer = userdata;
 
   98    size_t realsize = size * nmemb;
 
  105    memcpy(rawdata, 
contents, realsize);
 
  106    rawdata[realsize] = 0;
 
 
  115    strcpy(metric->
value, 
"2");
 
 
  137        info->name = __func__;
 
  139        info->summary = 
"Test value generation/respecting in metrics";
 
  141            "Metrics have two ways to provide values when the HTTP callback\n" 
  143            "1. By using the direct value that resides in the metric\n" 
  144            "2. By providing a callback function to specify the value\n" 
  145            "This test verifies that both function appropriately when the\n" 
  146            "HTTP callback is called.";
 
  164    strcpy(test_counter_one.
value, 
"1");
 
  168    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
 
  169    res = curl_easy_perform(curl);
 
  170    if (res != CURLE_OK) {
 
  173        goto metric_values_cleanup;
 
  178        "# HELP test_counter_one A test counter\n" 
  179        "# TYPE test_counter_one counter\n" 
  180        "test_counter_one 1\n" 
  181        "# HELP test_counter_two A test counter\n" 
  182        "# TYPE test_counter_two counter\n" 
  183        "test_counter_two 2\n") != 
NULL, 
result, metric_values_cleanup);
 
  185metric_values_cleanup:
 
 
  209        .name = 
"test_callback",
 
  215        info->name = __func__;
 
  217        info->summary = 
"Test registration of callbacks";
 
  219            "This test covers callback registration. It registers\n" 
  220            "a callback that is invoked when an HTTP request is made,\n" 
  221            "and it verifies that during said callback the output to\n" 
  222            "the response string is correctly appended to. It also verifies\n" 
  223            "that unregistered callbacks are not invoked.";
 
  243    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
 
  244    res = curl_easy_perform(curl);
 
  245    if (res != CURLE_OK) {
 
  252        "# HELP test_counter A test counter\n" 
  253        "# TYPE test_counter counter\n" 
  254        "test_counter 0\n") != 
NULL);
 
 
  276        info->name = __func__;
 
  278        info->summary = 
"Test registration of metrics";
 
  280            "This test covers the following registration scenarios:\n" 
  281            "- Nominal registration of simple metrics\n" 
  282            "- Registration of metrics with different allocation strategies\n" 
  283            "- Nested metrics with label families\n" 
  284            "- Off nominal registration with simple name collisions\n" 
  285            "- Off nominal registration with label collisions";
 
  296    ast_test_validate(
test, test_gauge != 
NULL);
 
  302    ast_test_validate_cleanup(
test, test_gauge_child_one != 
NULL, 
result, metric_register_cleanup);
 
  306    ast_test_validate_cleanup(
test, test_gauge_child_two != 
NULL, 
result, metric_register_cleanup);
 
  312    ast_test_validate_cleanup(
test, test_gauge->children.first == test_gauge_child_one, 
result, metric_register_cleanup);
 
  313    ast_test_validate_cleanup(
test, test_gauge->children.last == test_gauge_child_two, 
result, metric_register_cleanup);
 
  317    ast_test_validate_cleanup(
test, bad_metric != 
NULL, 
result, metric_register_cleanup);
 
  324    ast_test_validate_cleanup(
test, bad_metric != 
NULL, 
result, metric_register_cleanup);
 
  333    test_gauge_child_two = 
NULL;
 
  341    test_gauge_child_one = 
NULL;
 
  350metric_register_cleanup:
 
 
  376        info->name = __func__;
 
  378        info->summary = 
"Test formatting of counters";
 
  380            "This test covers the formatting of printed counters";
 
  399        "# HELP test_counter A test counter\n" 
  400        "# TYPE test_counter counter\n" 
  402        "test_counter{key_one=\"value_one\",key_two=\"value_one\"} 0\n" 
  403        "test_counter{key_one=\"value_two\",key_two=\"value_two\"} 0\n") == 0);
 
 
  414        info->name = __func__;
 
  416        info->summary = 
"Test creation (and destruction) of malloc'd counters";
 
  418            "This test covers creating a counter metric and destroying\n" 
  419            "it. The metric should be malloc'd.";
 
  426    ast_test_validate(
test, metric != 
NULL);
 
  429    ast_test_validate(
test, !strcmp(metric->help, 
"A test counter"));
 
  430    ast_test_validate(
test, !strcmp(metric->name, 
"test_counter"));
 
  431    ast_test_validate(
test, !strcmp(metric->value, 
""));
 
  432    ast_test_validate(
test, metric->children.first == 
NULL);
 
  433    ast_test_validate(
test, metric->children.last == 
NULL);
 
 
  459        info->name = __func__;
 
  461        info->summary = 
"Test formatting of gauges";
 
  463            "This test covers the formatting of printed gauges";
 
  482        "# HELP test_gauge A test gauge\n" 
  483        "# TYPE test_gauge gauge\n" 
  485        "test_gauge{key_one=\"value_one\",key_two=\"value_one\"} 0\n" 
  486        "test_gauge{key_one=\"value_two\",key_two=\"value_two\"} 0\n") == 0);
 
 
  497        info->name = __func__;
 
  499        info->summary = 
"Test creation (and destruction) of malloc'd gauges";
 
  501            "This test covers creating a gauge metric and destroying\n" 
  502            "it. The metric should be malloc'd.";
 
  509    ast_test_validate(
test, metric != 
NULL);
 
  512    ast_test_validate(
test, !strcmp(metric->help, 
"A test gauge"));
 
  513    ast_test_validate(
test, !strcmp(metric->name, 
"test_gauge"));
 
  514    ast_test_validate(
test, !strcmp(metric->value, 
""));
 
  515    ast_test_validate(
test, metric->children.first == 
NULL);
 
  516    ast_test_validate(
test, metric->children.last == 
NULL);
 
 
  530        info->name = __func__;
 
  532        info->summary = 
"Test basic auth handling";
 
  534            "This test covers authentication of requests";
 
  557    res = curl_easy_perform(curl);
 
  558    if (res != CURLE_OK) {
 
  562    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
 
  564    ast_test_validate(
test, response_code == 401);
 
  568    curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
 
  569    curl_easy_setopt(curl, CURLOPT_USERPWD, 
"matt:jordan");
 
  570    res = curl_easy_perform(curl);
 
  571    if (res != CURLE_OK) {
 
  575    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
 
  577    ast_test_validate(
test, response_code == 401);
 
  581    curl_easy_setopt(curl, CURLOPT_USERPWD, 
"foo:bar");
 
  582    res = curl_easy_perform(curl);
 
  583    if (res != CURLE_OK) {
 
  587    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
 
  589    ast_test_validate(
test, response_code == 200);
 
 
  603        info->name = __func__;
 
  605        info->summary = 
"Test handling of enable/disable";
 
  607            "When disabled, the module should return a 503.\n" 
  608            "This test verifies that it actually occurs.";
 
  629    res = curl_easy_perform(curl);
 
  630    if (res != CURLE_OK) {
 
  634    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
 
  636    ast_test_validate(
test, response_code == 503);
 
 
  650        info->name = __func__;
 
  652        info->summary = 
"Test producing core metrics";
 
  654            "This test covers the core metrics that are produced\n" 
  655            "by the basic Prometheus module.";
 
  670    config->core_metrics_enabled = 1;
 
  682    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
 
  683    res = curl_easy_perform(curl);
 
  684    if (res != CURLE_OK) {
 
 
  717    while ((
str = strstr(
str, needle))) {
 
  718        str += strlen(needle);
 
 
  734        info->name = __func__;
 
  736        info->summary = 
"Test producing bridge metrics";
 
  738            "This test covers checking the metrics produced by the\n" 
  739            "bridge support of the basic Promtheus module.";
 
  746    ast_test_validate(
test, bridge1 != 
NULL);
 
  750        "test_res_prometheus", 
"test_bridge_invisible", 
NULL);
 
  753    ast_test_validate(
test, bridge3 != 
NULL);
 
  763    ast_test_validate(
test, 
match_count(
ast_str_buffer(response), 
"# HELP asterisk_bridges_channels_count Number of channels in the bridge.") == 1);
 
 
  773    const char *bindport;
 
 
  819    if (!new_module_config) {
 
  827    ao2_ref(new_module_config, -1);
 
 
  896    .
requires = 
"res_prometheus",
 
Asterisk main include file. File version handling, generic pbx functions.
#define AST_CURL_USER_AGENT
#define ast_malloc(len)
A wrapper for malloc()
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
struct ast_bridge * ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Create a new base class bridge.
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
@ AST_BRIDGE_CAPABILITY_HOLDING
Basic bridge subclass API.
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
@ AST_BRIDGE_FLAG_INVISIBLE
struct ast_sockaddr bindaddr
static const char config[]
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
static char prefix[MAX_PREFIX]
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
@ CONFIG_FLAG_FILEUNCHANGED
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
struct ast_str * prometheus_scrape_to_string(void)
Get the raw output of what a scrape would produce.
Asterisk Prometheus Metrics.
int prometheus_metric_unregister(struct prometheus_metric *metric)
Remove a registered metric.
#define PROMETHEUS_METRIC_SET_LABEL(metric, label, n, v)
Convenience macro for setting a label / value in a metric.
int prometheus_metric_register(struct prometheus_metric *metric)
int prometheus_metric_registered_count(void)
void prometheus_general_config_set(struct prometheus_general_config *config)
Set the configuration for the module.
#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.
struct prometheus_metric * prometheus_gauge_create(const char *name, const char *help)
Create a malloc'd gauge metric.
void prometheus_callback_unregister(struct prometheus_callback *callback)
Remove a registered callback.
void * prometheus_general_config_alloc(void)
Allocate a new configuration object.
void prometheus_metric_free(struct prometheus_metric *metric)
Destroy a metric and all its children.
void prometheus_metric_to_string(struct prometheus_metric *metric, struct ast_str **output)
Convert a metric (and its children) into Prometheus compatible text.
int prometheus_callback_register(struct prometheus_callback *callback)
struct prometheus_general_config * prometheus_general_config_get(void)
Retrieve the current configuration of the module.
@ PROMETHEUS_METRIC_MALLOCD
The metric was allocated on the heap.
struct prometheus_metric * prometheus_counter_create(const char *name, const char *help)
Create a malloc'd counter metric.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Structure that contains information about a bridge.
Structure used to handle boolean flags.
Support for dynamic strings.
Contains all the initialization information required to store a new test definition.
The configuration settings for this module.
Defines a callback that will be invoked when the HTTP route is called.
Prometheus general configuration.
const ast_string_field uri
const ast_string_field auth_password
const ast_string_field auth_username
An actual, honest to god, metric.
struct prometheus_metric::@289 children
A list of children metrics.
struct prometheus_metric::@290 entry
char value[PROMETHEUS_MAX_VALUE_LENGTH]
The current value.
#define AST_TEST_REGISTER(cb)
#define ast_test_status_update(a, b, c...)
#define AST_TEST_UNREGISTER(cb)
#define AST_TEST_DEFINE(hdr)
static void prometheus_metric_free_wrapper(void *ptr)
static int process_config(int reload)
static int match_count(const char *str, const char *needle)
static void metric_values_get_counter_value_cb(struct prometheus_metric *metric)
static void safe_bridge_destroy(struct ast_bridge *bridge)
static CURL * get_curl_instance(void)
static int test_init_cb(struct ast_test_info *info, struct ast_test *test)
static int reload_module(void)
static size_t curl_write_string_callback(void *contents, size_t size, size_t nmemb, void *userdata)
static void curl_free_wrapper(void *ptr)
static struct prometheus_general_config * config_alloc(void)
static int load_module(void)
struct prometheus_general_config * module_config
static void prometheus_metric_callback(struct ast_str **output)
static int unload_module(void)
static int test_cleanup_cb(struct ast_test_info *info, struct ast_test *test)
static char server_uri[512]
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.