-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ea402e3
Showing
23 changed files
with
2,818 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Virtual envirnoment | ||
/.venv/ | ||
|
||
# Python | ||
__pycache__/ | ||
*.pyc | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
FROM python:3.8.10-alpine | ||
|
||
ENV POETRY_VERSION=1.7.1 | ||
|
||
RUN apk update && apk add gcc musl-dev libffi-dev | ||
RUN addgroup -S dev && adduser -S dev -G dev | ||
|
||
USER dev | ||
|
||
RUN pip3 install --upgrade pip | ||
|
||
ADD --chown=dev:dev poetry.lock pyproject.toml /home/dev/asterisk-prometheus-exporter/ | ||
WORKDIR /home/dev/asterisk-prometheus-exporter/ | ||
ENV PATH="/home/dev/.local/bin/:${PATH}" | ||
|
||
RUN pip3 install --user "poetry==$POETRY_VERSION" | ||
RUN poetry install --only main | ||
|
||
ADD --chown=dev:dev src ./src | ||
CMD ["poetry", "run", "python", "src/main.py"] | ||
|
||
EXPOSE 8080 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright 2023 GONICUS GmbH | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# Asterisk prometheus exporter | ||
Repository that provides a dynamically configurable Prometheus exporter for Asterisk. The exporter uses the Asterisk Manager Interface (AMI) to communicate with Asterisk and YAML files to configure what data is scraped from Asterisk and what metrics are generated. This allows the exporter to be used with older Asterisk versions in different environments. | ||
|
||
## Installation | ||
### Python Poetry | ||
The exporter uses Poetry as it's dependency management. Head over to [Poetry](https://python-poetry.org/) to install the latest version for your desired platform. | ||
|
||
Install the required dependencies using Poetry: | ||
``` | ||
poetry install | ||
``` | ||
|
||
Start the exporter: | ||
``` | ||
poetry run python src/main.py | ||
``` | ||
The configured metrics can be accessed at http://localhost:8080. | ||
|
||
By default, the exporter loads the configuration `config.yml` and uses port 8080. \ | ||
A different port can be specified via the first positional argument: `poetry run python src/main.py 9090`. \ | ||
A different configuration can be set using the `--config` option: `poetry run python src/main.py --config path/to/config.yml`. | ||
|
||
### Docker | ||
Create a Docker image using the provided Dockerfile: | ||
``` | ||
docker build --tag asterisk-prometheus-exporter . | ||
``` | ||
|
||
Run the Docker image and mount the configuration: | ||
``` | ||
docker run -p 8080:8080 -v ./config.yml:/home/dev/asterisk-prometheus-exporter/config.yml asterisk-prometheus-exporter | ||
``` | ||
The configured metrics can be accessed at http://localhost:8080. | ||
|
||
## Configuration | ||
This section shows the rough structure of the configuration. See `src/config_schema.yml` for a detailed description of the configuration and what is possible. | ||
|
||
Before customizing the configuration, it is recommended to have a rough overview of the Asterisk Manager Interfance (AMI) and how it works. The next section uses AMI terms that will not be explained further. | ||
|
||
The configuration is generally structured in such a way that it is determined which events sent by the Asterisk are filtered and which metrics should be generated based on the events received and the data they contain. | ||
|
||
The first and only required section of the configuration is the `ami_client` section. Here you configure which Asterisk and which access data you should log in with. | ||
```yml | ||
ami_client: | ||
ip: "1.2.3.4" | ||
port: 5038 | ||
username: "ami_user" | ||
secret: "test" | ||
``` | ||
The `filter` section of the configuration is used to define filter, which are used to collect events from the Asterisk that are send to the AMI client when an event is triggered within the Asterisk. An event that falls under this, for example, is the DialBegin event, which is sent by the Asterisk when a dial action is started. The filters defined in this section are used from the start of the exporter until the end. For each filter, you first define which events should be filter and then which metrics should be generated from the filtered events. \ | ||
The following example shows a configuration that counts how many calls are made: | ||
```yml | ||
filter: | ||
- event: "DialBegin" | ||
metrics: | ||
- name: "dial_count" | ||
description: "Total number of started dials" | ||
value: | ||
type: counter # Currently supported open metric types: counter, gauge | ||
increment_value: "1" # Increment the metric value every time a DialBegin event is received | ||
``` | ||
|
||
The `scrape` section is used to define actions that are send to the AMI in a specific interval. Here you first determine the interval at which the scraping is taking place. A list is then specified which actions should be sent to the AMI, which events should then be filtered and the metrics that should be generated based on the filtered events. The attribute `until` is used to set which event is expected to be the last event of the action. \ | ||
The following example shows a configuration that counts how many members are logged into a specific queue: | ||
```yml | ||
scrape: | ||
interval: 15 # Send the actions every 15 seconds | ||
actions: | ||
- name: "QueueStatus" # Action that should be sent | ||
collect: | ||
# Events to filter after sending the action | ||
- event: "QueueMember" | ||
metrics: | ||
- name: "queue_member_count" | ||
description: "Number of members currently logged into a specific queue" | ||
value: | ||
type: gauge | ||
increment_value: "1" | ||
value_on_scrape_start: 0 | ||
labels: | ||
- name: "queue" | ||
value: "$Queue" # Use '$' to access attributes from the filtered event | ||
until: "ContactStatusDetailComplete" | ||
``` | ||
|
||
## Example configuration | ||
Below is an entire example configuration that scrapes the RTCP fraction lost of the known endpoints and counts the number of members currently logged into a specific queue. \ | ||
This configuration allows, for example, to send an alert if too few members are logged into a queue or to see whether a user agent has connection problems. | ||
```yml | ||
ami_client: | ||
ip: "1.2.3.4" | ||
port: 5038 | ||
username: "ami_user" | ||
secret: "test" | ||
filter: | ||
- event: "RTCPSend|RTCPReceived" | ||
metrics: | ||
- name: "rtcp_endpoint_x_fraction_lost" | ||
description: "Aggregate fraction lost of RTCP events" | ||
value: | ||
type: counter | ||
increment_value: "$Report0FractionLost" | ||
labels: | ||
- name: "endpoint" | ||
value: "$CallerIDNum" | ||
scrape: | ||
interval: 15 | ||
actions: | ||
- name: "QueueStatus" | ||
collect: | ||
- event: "QueueMember" | ||
metrics: | ||
- name: "queue_member_count" | ||
description: "Number of members currently logged into a specific queue" | ||
value: | ||
type: gauge | ||
increment_value: "1" | ||
value_on_scrape_start: 0 | ||
labels: | ||
- name: "queue" | ||
value: "$Queue" | ||
until: "QueueStatusComplete" | ||
``` | ||
The metrics generated based on the configuration might look like this: | ||
``` | ||
# HELP rtcp_endpoint_x_fraction_lost_total Aggregate fraction lost of RTCP events | ||
# TYPE rtcp_endpoint_x_fraction_lost_total counter | ||
rtcp_endpoint_x_fraction_lost_total{endpoint="100"} 0.0 | ||
rtcp_endpoint_x_fraction_lost_total{endpoint="200"} 255.0 | ||
rtcp_endpoint_x_fraction_lost_total{endpoint="300"} 291.0 | ||
# HELP rtcp_endpoint_x_fraction_lost_created Aggregate fraction lost of RTCP events | ||
# TYPE rtcp_endpoint_x_fraction_lost_created gauge | ||
rtcp_endpoint_x_fraction_lost_created{endpoint="100"} 1.7026356281841428e+09 | ||
rtcp_endpoint_x_fraction_lost_created{endpoint="200"} 1.702635652441021e+09 | ||
rtcp_endpoint_x_fraction_lost_created{endpoint="300"} 1.7026356524437878e+09 | ||
# HELP queue_member_count Number of members currently logged into a specific queue | ||
# TYPE queue_member_count gauge | ||
queue_member_count{queue="zentrale"} 2.0 | ||
queue_member_count{queue="support"} 2.0 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# Base exporter config | ||
ami_client: | ||
ip: "<ip>" | ||
port: 5038 | ||
username: '<username>' | ||
secret: '<secret>' | ||
|
||
# General config | ||
general: | ||
log_level: "DEBUG" | ||
login_validation_timeout: 10 | ||
response_timeout: 10 | ||
ping_timeout: 20 | ||
|
||
|
||
# Default settings | ||
default: | ||
scrape_interval: 15 | ||
action_response_timeout: 5 | ||
action_event_timeout: 15 | ||
action_priority: 1 | ||
action_context: "default" | ||
action_caller_id: "python" | ||
|
||
# Filter config | ||
filter: | ||
- event: "RTCPSend|RTCPReceived" | ||
metrics: | ||
- name: "rtcp_endpoint_x_fraction_lost" | ||
description: "Aggregate fraction lost of RTCP events" | ||
value: | ||
type: counter | ||
increment_value: "$Report0FractionLost" | ||
labels: | ||
- name: "endpoint" | ||
value: "$CallerIDNum" | ||
- name: "rtcp_endpoint_x_cumulative_lost" | ||
description: "Aggregate cumulative lost of RTCP events" | ||
value: | ||
type: counter | ||
increment_value: "$Report0CumulativeLost" | ||
labels: | ||
- name: "endpoint" | ||
value: "$CallerIDNum" | ||
|
||
# Action config | ||
scrape: | ||
interval: 15 | ||
actions: | ||
- name: "QueueStatus" | ||
collect: | ||
- event: "QueueParams" | ||
metrics: | ||
- name: "queue_total" | ||
description: "Available queues" | ||
value: | ||
type: gauge | ||
set_value: "1" | ||
labels: | ||
- name: "queue" | ||
value: "$Queue" | ||
- event: "QueueMember" | ||
metrics: | ||
- name: "queue_member_count" | ||
description: "Number of members currently logged into a specific queue" | ||
value: | ||
type: gauge | ||
increment_value: "1" | ||
value_on_scrape_start: 0 | ||
labels: | ||
- name: "queue" | ||
value: "$Queue" | ||
- event: "QueueEntry" | ||
metrics: | ||
- name: "queue_entry_count" | ||
description: "Number of entries in a specific queue" | ||
value: | ||
type: gauge | ||
increment_value: "1" | ||
value_on_scrape_start: 0 | ||
labels: | ||
- name: "queue" | ||
value: "$Queue" | ||
until: "QueueStatusComplete" | ||
- name: "PJSIPShowRegistrationInboundContactStatuses" | ||
collect: | ||
- event: "ContactStatusDetail" | ||
metrics: | ||
- name: "user_agents" | ||
description: "User agents" | ||
value: | ||
type: gauge | ||
increment_value: "1" | ||
value_on_scrape_start: 0 | ||
labels: | ||
- name: "user_agent" | ||
value: "$UserAgent" | ||
until: "ContactStatusDetailComplete" |
Oops, something went wrong.