Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ env:
- DD_AGENT_BRANCH=master
matrix:
- TRAVIS_FLAVOR=default
- TRAVIS_FLAVOR=asterisk FLAVOR_VERSION=latest
# END OF TRAVIS MATRIX

before_install:
Expand Down
32 changes: 32 additions & 0 deletions asterisk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Asterisk Integration

## Overview

Get metrics from asterisk service in real time to:

* Visualize and monitor asterisk states
* Be notified about asterisk failovers and events.

## Installation

Install the `dd-check-asterisk` package manually or with your favorite configuration manager

## Configuration

Edit the `asterisk.yaml` file to point to your server and port, set the masters to monitor

## Validation

When you run `datadog-agent info` you should see something like the following:

Checks
======

asterisk
-----------
- instance #0 [OK]
- Collected 39 metrics, 0 events & 7 service checks

## Compatibility

The asterisk check is compatible with all major platforms
175 changes: 175 additions & 0 deletions asterisk/check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# stdlib
import re

# 3rd party
import asterisk.manager

# project
from checks import AgentCheck

EVENT_TYPE = SOURCE_TYPE_NAME = 'asterisk'

#
# requires pyst2 for Asterisk Manager Interface
# https://github.com/rdegges/pyst2
#
# requires re for regular expression matching on asterisk output
#
#
class AsteriskCheck(AgentCheck):

def __init__(self, name, init_config, agentConfig, instances=None):
AgentCheck.__init__(self, name, init_config, agentConfig, instances)

def check(self, instance):
if 'host' not in instance:
instance['host'] = 'localhost'
if 'manager_user' not in instance:
self.log.error('manager_user not defined, skipping')
return
if 'manager_secret' not in instance:
self.log.error('manager_secret not defined, skipping')
return


###### Connect
mgr = asterisk.manager.Manager()
try:
if 'port' in instance:
mgr.connect(instance['host'],instance['port'])
else:
mgr.connect(instance['host'])
mgr.login(instance['manager_user'],instance['manager_secret'])
except asterisk.manager.ManagerSocketException as e:
self.log.error('Error connecting to Asterisk Manager Interface')
mgr.close()
return
except asterisk.manager.ManagerAuthException as e:
self.log.error('Error Logging in to Asterisk Manager Interface')
mgr.close()
return

##### Call Volume
call_volume = mgr.command('core show calls')

current_call_vol = call_volume.data.split('\n')

current_call_vol = current_call_vol[0].replace('active call','')
current_call_vol = current_call_vol.replace('s','')
current_call_vol = current_call_vol.replace(' ','')

self.gauge('asterisk.callvolume',current_call_vol)

##### SIP Peers
sip_result = mgr.command('sip show peers')

sip_results = sip_result.data.split('\n')

siptotals = sip_results[len(sip_results)-3]

siptotal = re.findall(r'([0-9]+) sip peer',siptotals)[0]

monitored_peers = re.findall(r'Monitored: ([0-9]+) online, ([0-9]+) offline',siptotals)[0]
unmonitored_peers = re.findall(r'Unmonitored: ([0-9]+) online, ([0-9]+) offline',siptotals)[0]

self.gauge('asterisk.sip.peers',siptotal)
self.gauge('asterisk.sip.monitored.online',monitored_peers[0])
self.gauge('asterisk.sip.monitored.offline',monitored_peers[1])
self.gauge('asterisk.sip.unmonitored.online',unmonitored_peers[0])
self.gauge('asterisk.sip.unmonitored.offline',unmonitored_peers[1])

##### SIP Trunks (You have to add '-trunk' string into your SIP trunk name to detect it as a Trunk)
sip_total_trunks = 0
sip_online_trunks = 0
sip_offline_trunks = 0


for chan in sip_results:
if chan != None:
chan_data = chan.split()

if len(chan_data) > 1:
if "-trunk" in chan_data[0]:
sip_total_trunks += 1
if len(chan_data) > 2 and "OK" in chan_data[5]:
sip_online_trunks += 1
if len(chan_data) > 2 and chan_data[5] == "UNREACHABLE":
sip_offline_trunks += 1

self.gauge('asterisk.sip.trunks.total',sip_total_trunks)
self.gauge('asterisk.sip.trunks.online',sip_online_trunks)
self.gauge('asterisk.sip.trunks.offline',sip_offline_trunks)

##### PRI In Use

pri = mgr.command('pri show channels')

pri_channels = pri.data.split('\n')

pri_channels[0] = None
pri_channels[1] = None

openchannels = 0
for chan in pri_channels:
if chan != None:
chan_data = chan.split()
if len(chan_data) > 2 and chan_data[3] == "No":
openchannels += 1

self.gauge('asterisk.pri.channelsinuse',openchannels)

##### IAX2 Peers

iax_result = mgr.command('iax2 show peers')

iax_results = iax_result.data.split('\n')

iax_total_line = iax_results[len(iax_results)-3]

iax_peers_total = re.findall(r'([0-9]+) iax2 peers',iax_total_line)[0]
iax_peers_online = re.findall(r'\[([0-9]+) online',iax_total_line)[0]
iax_peers_offline = re.findall(r'([0-9]+) offline',iax_total_line)[0]
iax_peers_unmonitored = re.findall(r'([0-9]+) unmonitored',iax_total_line)[0]

self.gauge('asterisk.iax2.peers',iax_peers_total)
self.gauge('asterisk.iax2.online',iax_peers_online)
self.gauge('asterisk.iax2.offline',iax_peers_offline)
self.gauge('asterisk.iax2.unmonitored',iax_peers_unmonitored)

##### DAHDI Channels

dahdi_result = mgr.command('dahdi show status')

dahdi_results = dahdi_result.data.split('\n')

dahdi_total_trunks = len(dahdi_results)-3

dahdi_results[0] = None

dahdi_online_trunks = 0
dahdi_offline_trunks = 0

for chan in dahdi_results:
if chan != None:
chan_data = chan.split()

if len(chan_data) > 1:
if "Wildcard" in chan_data[0]:
if len(chan_data) > 2 and chan_data[2] == "OK":
dahdi_online_trunks += 1
if len(chan_data) > 2 and chan_data[2] == "RED":
dahdi_offline_trunks += 1

if "wanpipe" in chan_data[0]:
if len(chan_data) > 2 and chan_data[3] == "OK":
dahdi_online_trunks += 1
if len(chan_data) > 2 and chan_data[3] == "RED":
dahdi_offline_trunks += 1

self.gauge('asterisk.dahdi.total',dahdi_total_trunks)
self.gauge('asterisk.dahdi.online',dahdi_online_trunks)
self.gauge('asterisk.dahdi.offline',dahdi_offline_trunks)

##### Close connection

mgr.close()
64 changes: 64 additions & 0 deletions asterisk/ci/asterisk.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
require 'ci/common'

def asterisk_version
ENV['FLAVOR_VERSION'] || 'latest'
end

def asterisk_rootdir
"#{ENV['INTEGRATIONS_DIR']}/asterisk_#{asterisk_version}"
end

namespace :ci do
namespace :asterisk do |flavor|
task before_install: ['ci:common:before_install']

task install: ['ci:common:install'] do
use_venv = in_venv
install_requirements('asterisk/requirements.txt',
"--cache-dir #{ENV['PIP_CACHE']}",
"#{ENV['VOLATILE_DIR']}/ci.log", use_venv)
# sample docker usage
# sh %(docker create -p XXX:YYY --name asterisk source/asterisk:asterisk_version)
# sh %(docker start asterisk)
end

task before_script: ['ci:common:before_script']

task script: ['ci:common:script'] do
this_provides = [
'asterisk'
]
Rake::Task['ci:common:run_tests'].invoke(this_provides)
end

task before_cache: ['ci:common:before_cache']

task cleanup: ['ci:common:cleanup']
# sample cleanup task
# task cleanup: ['ci:common:cleanup'] do
# sh %(docker stop asterisk)
# sh %(docker rm asterisk)
# end

task :execute do
exception = nil
begin
%w(before_install install before_script).each do |u|
Rake::Task["#{flavor.scope.path}:#{u}"].invoke
end
Rake::Task["#{flavor.scope.path}:script"].invoke
Rake::Task["#{flavor.scope.path}:before_cache"].invoke
rescue => e
exception = e
puts "Failed task: #{e.class} #{e.message}".red
end
if ENV['SKIP_CLEANUP']
puts 'Skipping cleanup, disposable environments are great'.yellow
else
puts 'Cleaning up'
Rake::Task["#{flavor.scope.path}:cleanup"].invoke
end
raise exception if exception
end
end
end
7 changes: 7 additions & 0 deletions asterisk/conf.yaml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
instances:
- host: localhost #defaults to localhost
port: 5038 #defaults to 5038
manager_user: user #required
manager_secret: secret #required

#this user needs to have the command write privilege
11 changes: 11 additions & 0 deletions asterisk/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"maintainer": "help@datadoghq.com",
"manifest_version": "0.1.0",
"max_agent_version": "6.0.0",
"min_agent_version": "5.6.3",
"name": "asterisk",
"short_description": "asterisk description.",
"support": "contrib",
"supported_os": ["linux","mac_os","windows"],
"version": "0.1.0"
}
1 change: 1 addition & 0 deletions asterisk/metadata.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name
1 change: 1 addition & 0 deletions asterisk/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# integration pip requirements
38 changes: 38 additions & 0 deletions asterisk/test_asterisk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# (C) Datadog, Inc. 2010-2016
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)

# stdlib
from nose.plugins.attrib import attr

# 3p

# project
from tests.checks.common import AgentCheckTest


instance = {
'host': 'localhost',
'port': 26379,
'password': 'datadog-is-devops-best-friend'
}


# NOTE: Feel free to declare multiple test classes if needed

@attr(requires='asterisk')
class TestAsterisk(AgentCheckTest):
"""Basic Test for asterisk integration."""
CHECK_NAME = 'asterisk'

def test_check(self):
"""
Testing Asterisk check.
"""
self.load_check({}, {})

# run your actual tests...

self.assertTrue(True)
# Raises when COVERAGE=true and coverage < 100%
self.coverage_report()
1 change: 1 addition & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ test:
override:
- bundle exec rake prep_travis_ci
- rake ci:run[default]
- rake ci:run[asterisk]
- bundle exec rake requirements
post:
- if [[ $(docker ps -a -q) ]]; then docker stop $(docker ps -a -q); fi