Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Merge pull request #115 from DataDog/conor/monitor-apis
Browse files Browse the repository at this point in the history
Add monitor and downtime APIs with integration tests.
  • Loading branch information
conorbranagan committed Nov 17, 2014
2 parents 725c842 + e7c6aba commit 61306be
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 1 deletion.
15 changes: 15 additions & 0 deletions src/dogapi/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,18 @@ class MetricType(object):
Gauge = "gauge"
Counter = "counter"
Histogram = "histogram"


class MonitorType(object):
SERVICE_CHECK = 'service check'
METRIC_ALERT = 'metric alert'
QUERY_ALERT = 'query alert'
ALL = (SERVICE_CHECK, METRIC_ALERT, QUERY_ALERT)


class CheckStatus(object):
OK = 0
WARNING = 1
CRITICAL = 2
UNKNOWN = 3
ALL = (OK, WARNING, CRITICAL, UNKNOWN)
5 changes: 4 additions & 1 deletion src/dogapi/http/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
from dogapi.http.users import *
from dogapi.http.snapshot import *
from dogapi.http.screenboards import *
from dogapi.http.monitors import *
from dogapi.http.service_check import *

class DogHttpApi(BaseDatadog, HttpMetricApi, EventApi, DashApi, InfrastructureApi,
AlertApi, UserApi, SnapshotApi, ScreenboardApi):
AlertApi, UserApi, SnapshotApi, ScreenboardApi, MonitorApi, DowntimeApi,
ServiceCheckApi):
"""
A high-level client for interacting with the Datadog API.
Expand Down
1 change: 1 addition & 0 deletions src/dogapi/http/alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
]

class AlertApi(object):
""" DEPRECATED: Used the methods in `MonitorApi` instead. """

def alert(self, query, name=None, message=None, silenced=False,
notify_no_data=None, timeout_h=None):
Expand Down
199 changes: 199 additions & 0 deletions src/dogapi/http/monitors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
__all__ = [
'DowntimeApi',
'MonitorApi',
'MonitorType',
]

from dogapi.constants import MonitorType
from dogapi.exceptions import ApiError

class MonitorApi(object):

def monitor(self, mtype, query, name=None, message=None, options=None):
"""
Create a new monitor of type *mtype* with the given *name* and *query*.
The *message* will accompany any notifications sent for the alert and
can contain the same '@' notation as events to alert individual users.
The *options* argument is a dictionary of settings for the monitor.
See the Datadog API documentation for a break down of available options.
>>> dog_http_api.monitor("metric alert", "sum(last_1d):sum:system.net.bytes_rcvd{host:host0} > 100")
"""
mtype = mtype.lower()
if mtype not in MonitorType.ALL:
raise ApiError('Invalid monitor type, expected one of: %s' \
% ', '.join(MonitorType.ALL))

body = {
'type': mtype,
'query': query,
}

if name:
body['name'] = name
if message:
body['message'] = message
if options:
if not isinstance(options, dict):
raise ApiError('Invalid type for `options`, expected `dict`.')
body['options'] = options

return self.http_request('POST', '/monitor', body,
response_formatter=lambda x: x['id'],
)

def update_monitor(self, monitor_id, query, name=None, message=None,
options=None):
"""
Update the monitor identified by *monitor_id* with the given *query*.
The *message* will accompany any notifications sent for the alert and
can contain the same '@' notation as events to alert individual users.
The *options* argument is a dictionary of settings for the monitor.
See the Datadog API documentation for a break down of available options.
>>> dog_http_api.update_monitor(1234, "sum(last_1d):sum:system.net.bytes_rcvd{host:host0} > 200")
"""
body = {
'query': query
}
if name:
body['name'] = name
if message:
body['message'] = message
if options:
body['options'] = options

return self.http_request('PUT', '/monitor/%s' % monitor_id, body,
response_formatter=lambda x: x['id'],
)

def get_monitor(self, monitor_id, group_states=None):
"""
Get the details for the monitor identified by *monitor_id*.
*group_states* is optionally a list of statuses chosen from "all", "ok",
"warn", "alert", "no data". For example, if you want only the failing
groups then you would set it to ['alert', 'warn']. If no value is given
then no group states will be returned.
>>> dog_http_api.get_monitor(1234, group_states=['all'])
"""
params = {}

if group_states:
params['group_states'] = ','.join(group_states)

return self.http_request('GET', '/monitor/%s' % monitor_id, **params)

def delete_monitor(self, monitor_id):
"""
Delete the monitor identified by *monitor_id*.
>>> dog_http_api.delete_monitor(1234)
"""

return self.http_request('DELETE', '/monitor/%s' % monitor_id)

def get_all_monitors(self, group_states=None):
"""
Get the details for all monitors. If *include_state* is set to True then
the response will include the state of each active group in the alert.
*group_states* is optionally a list of statuses chosen from "all", "ok",
"warn", "alert", "no data". For example, if you want only the failing
groups then you would set it to ['alert', 'warn']. If no value is given
then no group states will be returned.
>>> dog_http_api.get_all_monitors(group_states=['alert'])
"""
params = {}

if group_states:
params['group_states'] = ','.join(group_states)

return self.http_request('GET', '/monitor', **params)

def mute_monitors(self):
"""
Mute all monitors.
>>> dog_http_api.mute_monitors()
"""

return self.http_request('POST', '/monitor/mute_all')

def unmute_monitors(self):
"""
Unmute all monitors.
>>> dog_http_api.unmute_monitors()
"""

return self.http_request('POST', '/monitor/unmute_all')

def mute_monitor(self, monitor_id, scope=None, end=None):
"""
Mute the monitor identified by *monitor_id*. If a *scope* is given your
mute will just apply to that scope. You can give an *end* argument that
is a POSIX timestamp of when the mute should stop.
>>> dog_http_api.mute_monitor(1234, scope='env:staging')
"""
body = {}
if scope:
body['scope'] = scope
if end:
body['end'] = end
return self.http_request('POST', '/monitor/%s/mute' % monitor_id, body)

def unmute_monitor(self, monitor_id, scope=None):
"""
Unmute the monitor identified by *monitor_id*. If a *scope* is given
your unmute will just apply to that scope.
>>> dog_http_api.unmute_monitors(1234, scope='env:staging')
"""
body = {}
if scope:
body['scope'] = scope
return self.http_request('POST', '/monitor/%s/unmute' % monitor_id, body)


class DowntimeApi(object):

def schedule_downtime(self, scope, start, end=None):
"""
Schedule downtime over *scope* from *start* to *end*, where *start* and
*end* are POSIX timestamps. If *end* is omitted then the downtime will
continue until cancelled.
"""
body = {
'scope': scope,
'start': start,
}
if end:
body['end'] = end
return self.http_request('POST', '/downtime', body,
response_formatter=lambda x: x['id'],
)

def get_downtime(self, downtime_id):
"""
Get the downtime identified by *downtime_id*
"""
return self.http_request('GET', '/downtime/%s' % downtime_id)

def cancel_downtime(self, downtime_id):
"""
Cancel the downtime identified by *downtime_id*
"""
return self.http_request('DELETE', '/downtime/%s' % downtime_id)

def get_all_downtimes(self, current_only=False):
"""
List all scheduled downtimes.
"""
params = {}
if current_only:
params['current_only'] = True
return self.http_request('GET', '/downtime', **params)
29 changes: 29 additions & 0 deletions src/dogapi/http/service_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
__all__ = [
'ServiceCheckApi',
]

import logging
import time
from dogapi.constants import CheckStatus
from dogapi.exceptions import ApiError

logger = logging.getLogger('dd.dogapi')


class ServiceCheckApi(object):
def service_check(self, check, host, status, timestamp=None, message=None, tags=None):
if status not in CheckStatus.ALL:
raise ApiError('Invalid status, expected one of: %s' \
% ', '.join(CheckStatus.ALL))

body = {
'check': check,
'host_name': host,
'timestamp': timestamp or time.time(),
'status': status
}
if message:
body['message'] = message
if tags:
body['tags'] = tags
return self.http_request('POST', '/check_run', body)
Loading

0 comments on commit 61306be

Please sign in to comment.