Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add authentication and timeout options #3214

Merged
merged 1 commit into from
Feb 27, 2019
Merged
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
5 changes: 2 additions & 3 deletions aerospike/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ Get metrics from Aerospike Database in real time to:
* Visualize and monitor Aerospike states
* Be notified about Aerospike failovers and events.

Note: Authentication and TLS are not supported.

## Setup

### Installation
Expand All @@ -34,7 +32,8 @@ See [metadata.csv][5] for a list of metrics provided by this integration.

### Service Checks

Aerospike does not include any service checks.
- `aerospike.can_connect`
- `aerospike.cluster_up`

### Events

Expand Down
25 changes: 21 additions & 4 deletions aerospike/datadog_checks/aerospike/aerospike.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,20 @@ class AerospikeCheck(AgentCheck):
def __init__(self, name, init_config, instances):
super(AerospikeCheck, self).__init__(name, init_config, instances)

# https://www.aerospike.com/apidocs/python/aerospike.html#aerospike.client
host = self.instance.get('host', 'localhost')
port = int(self.instance.get('port', 3000))
tls_name = self.instance.get('tls_name')
self._host = (host, port, tls_name) if tls_name else (host, port)

# https://www.aerospike.com/apidocs/python/client.html#aerospike.Client.connect
self._username = self.instance.get('username')
self._password = self.instance.get('password')

# In milliseconds, see https://www.aerospike.com/apidocs/python/client.html#aerospike-info-policies
timeout = int(self.instance.get('timeout', 10)) * 1000
self._info_policies = {'timeout': timeout}

self._host = (host, port)
self._metrics = set(self.instance.get('metrics', []))
self._namespace_metrics = set(self.instance.get('namespace_metrics', []))
self._required_namespaces = self.instance.get('namespaces')
Expand All @@ -85,33 +95,39 @@ def check(self, instance):

self._client = client

# https://www.aerospike.com/docs/reference/info/#statistics
self.collect_info('statistics', CLUSTER_METRIC_TYPE, required_keys=self._metrics, tags=self._tags)

# https://www.aerospike.com/docs/reference/info/#namespaces
namespaces = self.get_namespaces()

for ns in namespaces:
namespace_tags = ['namespace:{}'.format(ns)]
namespace_tags.extend(self._tags)

# https://www.aerospike.com/docs/reference/info/#namespace
self.collect_info(
'namespace/{}'.format(ns),
NAMESPACE_METRIC_TYPE,
required_keys=self._namespace_metrics,
tags=namespace_tags
)

# https://www.aerospike.com/docs/reference/info/#sindex
sindex = self.get_info('sindex/{}'.format(ns))
for idx in parse_namespace(sindex[:-1], ns, 'indexname'):
sindex_tags = ['sindex:{}'.format(idx)]
sindex_tags.extend(namespace_tags)
self.collect_info('sindex/{}/{}'.format(ns, idx), SINDEX_METRIC_TYPE, tags=sindex_tags)

# https://www.aerospike.com/docs/reference/info/#sets
sets = self.get_info('sets/{}'.format(ns))
for s in parse_namespace(sets, ns, 'set'):
set_tags = ['set:{}'.format(s)]
set_tags.extend(namespace_tags)
self.collect_info('sets/{}/{}'.format(ns, s), SET_METRIC_TYPE, separator=':', tags=set_tags)

# https://www.aerospike.com/docs/reference/info/#throughput
self.collect_throughput(namespaces)

self.service_check(SERVICE_CHECK_UP, self.OK, tags=self._tags)
Expand Down Expand Up @@ -149,7 +165,7 @@ def get_namespaces(self):

def get_client(self):
try:
client = aerospike.client({'hosts': [self._host]}).connect()
client = aerospike.client({'hosts': [self._host]}).connect(self._username, self._password)
except Exception as e:
self.log.error('Unable to connect to database: {}'.format(e))
self.service_check(SERVICE_CHECK_CONNECT, self.CRITICAL, tags=self._tags)
Expand All @@ -158,8 +174,9 @@ def get_client(self):
return client

def get_info(self, command, separator=';'):
# command\tKEY=VALUE;KEY=VALUE;...
data = self._client.info_node(command, self._host)
# See https://www.aerospike.com/docs/reference/info/
# Example output: command\tKEY=VALUE;KEY=VALUE;...
data = self._client.info_node(command, self._host, self._info_policies)

# Get rid of command and whitespace
data = data[len(command):].strip()
Expand Down
25 changes: 23 additions & 2 deletions aerospike/datadog_checks/aerospike/data/conf.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,29 @@ instances:
#
port: 3000

## @param tags - list of key:value elements - optional
## List of tags to attach to every metric, event and service check emitted by this integration.
## @param username - string - optional
## The database user to authenticate as.
#
# username: <USERNAME>

## @param password - string - optional
## The password of `username`.
#
# password: <PASSWORD>

## @param tls_name - string - optional
## This must match the tls-name specified in the node’s server
## configuration file and match the server’s CA certificate.
#
# tls_name: <TLS_NAME>

## @param timeout - integer - optional - default: 10
## The read timeout in seconds.
#
# timeout: 10

## @param tags - list of key:value strings - optional
## List of tags to attach to every metric and service check emitted by this integration.
##
## Learn more about tagging: https://docs.datadoghq.com/tagging/
#
Expand Down