Repository URL to install this package:
|
Version:
1:7.26.0-1 ▾
|
datadog-agent
/
opt
/
datadog-agent
/
embedded
/
lib
/
python3.8
/
site-packages
/
datadog_checks
/
apache
/
apache.py
|
|---|
# (C) Datadog, Inc. 2010-present
# All rights reserved
# Licensed under Simplified BSD License (see LICENSE)
import re
from six.moves.urllib.parse import urlparse
from datadog_checks.base import AgentCheck
class Apache(AgentCheck):
"""Tracks basic connection/requests/workers metrics
See http://httpd.apache.org/docs/2.2/mod/mod_status.html for more details
"""
GAUGES = {
'IdleWorkers': 'apache.performance.idle_workers',
'BusyWorkers': 'apache.performance.busy_workers',
'CPULoad': 'apache.performance.cpu_load',
'Uptime': 'apache.performance.uptime',
'Total kBytes': 'apache.net.bytes',
'Total Accesses': 'apache.net.hits',
'ConnsTotal': 'apache.conns_total',
'ConnsAsyncWriting': 'apache.conns_async_writing',
'ConnsAsyncKeepAlive': 'apache.conns_async_keep_alive',
'ConnsAsyncClosing': 'apache.conns_async_closing',
}
RATES = {'Total kBytes': 'apache.net.bytes_per_s', 'Total Accesses': 'apache.net.request_per_s'}
HTTP_CONFIG_REMAPPER = {
'apache_user': {'name': 'username'},
'apache_password': {'name': 'password'},
'disable_ssl_validation': {'name': 'tls_verify', 'invert': True, 'default': False},
'receive_timeout': {'name': 'read_timeout', 'default': 15},
'connect_timeout': {'name': 'connect_timeout', 'default': 5},
}
VERSION_REGEX = re.compile(r'Apache/(\d+(?:\.\d+)*)')
def __init__(self, name, init_config, instances):
super(Apache, self).__init__(name, init_config, instances)
self.assumed_url = {}
def check(self, instance):
if 'apache_status_url' not in instance:
raise Exception("Missing 'apache_status_url' in Apache config")
url = self.assumed_url.get(instance['apache_status_url'], instance['apache_status_url'])
tags = instance.get('tags', [])
# Submit a service check for status page availability.
parsed_url = urlparse(url)
apache_host = parsed_url.hostname
apache_port = parsed_url.port or 80
service_check_name = 'apache.can_connect'
service_check_tags = ['host:%s' % apache_host, 'port:%s' % apache_port] + tags
try:
self.log.debug(
'apache check initiating request, connect timeout %d receive %d',
self.http.options['timeout'][0],
self.http.options['timeout'][1],
)
r = self.http.get(url)
r.raise_for_status()
except Exception as e:
self.log.warning("Caught exception %s", e)
self.service_check(service_check_name, AgentCheck.CRITICAL, tags=service_check_tags)
raise
else:
self.service_check(service_check_name, AgentCheck.OK, tags=service_check_tags)
self.log.debug("apache check succeeded")
metric_count = 0
version_submitted = False
# Loop through and extract the numerical values
for line in r.iter_lines(decode_unicode=True):
values = line.split(': ')
if len(values) == 2: # match
metric, value = values
# Special case: fetch and submit the version
if metric == 'ServerVersion':
self._submit_metadata(value)
version_submitted = True
continue
try:
value = float(value)
except ValueError:
continue
# Special case: kBytes => bytes
if metric == 'Total kBytes':
value = value * 1024
# Send metric as a gauge, if applicable
if metric in self.GAUGES:
metric_count += 1
metric_name = self.GAUGES[metric]
self.gauge(metric_name, value, tags=tags)
# Send metric as a rate, if applicable
if metric in self.RATES:
metric_count += 1
metric_name = self.RATES[metric]
self.rate(metric_name, value, tags=tags)
if metric_count == 0:
if self.assumed_url.get(instance['apache_status_url']) is None and url[-5:] != '?auto':
self.assumed_url[instance['apache_status_url']] = '%s?auto' % url
self.warning("Assuming url was not correct. Trying to add ?auto suffix to the url")
self.check(instance)
return
else:
raise Exception(
("No metrics were fetched for this instance. Make sure that %s is the proper url.")
% instance['apache_status_url']
)
if not version_submitted:
# Can't get it from the mod_status output, try to get it from the server header even though
# it may not be exposed with some configurations.
server_version = r.headers.get("Server")
if server_version:
self._submit_metadata(server_version)
def _submit_metadata(self, value):
"""Possible formats:
Apache | Apache/X | Apache/X.Y | Apache/X.Y.Z | Apache/X.Y.Z (<OS>) | Apache/X.Y.Z (<OS>) <not specified>
https://httpd.apache.org/docs/2.4/mod/core.html#servertokens
"""
match = self.VERSION_REGEX.match(value)
if not match or not match.groups():
self.log.info("Cannot parse the complete Apache version from %s.", value)
return
version = match.group(1)
version_parts = {name: part for name, part in zip(('major', 'minor', 'patch'), version.split('.'))}
self.set_metadata('version', version, scheme='parts', final_scheme='semver', part_map=version_parts)
self.log.debug("found apache version %s", version)