monasca-agent/monasca_agent/collector/checks_d/apache.py

130 lines
5.3 KiB
Python

# (C) Copyright 2015 Hewlett Packard Enterprise Development Company LP
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# stdlib
import logging
import socket
from six.moves import urllib
# project
import monasca_agent.collector.checks as checks
import monasca_agent.collector.checks.services_checks as services_checks
import monasca_agent.collector.checks.utils as utils
import monasca_agent.common.util as util
log = logging.getLogger(__name__)
class Apache(checks.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_worker_count',
'BusyWorkers': 'apache.performance.busy_worker_count',
'CPULoad': 'apache.performance.cpu_load_perc',
'Total kBytes': 'apache.net.total_kbytes',
'Total Accesses': 'apache.net.hits',
}
RATES = {'Total kBytes': 'apache.net.kbytes_sec',
'Total Accesses': 'apache.net.requests_sec'
}
def __init__(self, name, init_config, agent_config, instances=None):
super(Apache, self).__init__(name, init_config, agent_config, instances)
self.url = None
def check(self, instance):
self.url = instance.get('apache_status_url', None)
if not self.url:
raise Exception("Missing 'apache_status_url' in Apache config")
req = urllib.request.Request(self.url, None, util.headers(self.agent_config))
apache_user = instance.get('apache_user', None)
apache_password = instance.get('apache_password', None)
if apache_user and apache_password:
utils.add_basic_auth(req, apache_user, apache_password)
else:
log.debug("Not using authentication for Apache Web Server")
# Submit a service check for status page availability.
parsed_url = urllib.parse.urlparse(self.url)
apache_host = parsed_url.hostname
apache_port = str(parsed_url.port or 80)
service_check_name = 'apache.status'
# Add additional dimensions
if apache_host == 'localhost':
# Localhost is not very useful, so get the actual hostname
apache_host = socket.gethostname()
dimensions = self._set_dimensions({'apache_host': apache_host,
'apache_port': apache_port,
'service': 'apache',
'component': 'apache'},
instance)
try:
request = urllib.request.urlopen(req)
except Exception as e:
self.log.info(
"%s is DOWN, error: %s. Connection failed." % (service_check_name, str(e)))
self.gauge(service_check_name, 1, dimensions=dimensions)
return services_checks.Status.DOWN, "%s is DOWN, error: %s. Connection failed." % (
service_check_name, str(e))
else:
self.log.debug("%s is UP" % service_check_name)
self.gauge(service_check_name, 0, dimensions=dimensions)
response = request.read()
metric_count = 0
# Loop through and extract the numerical values
for line in response.split('\n'):
values = line.split(': ')
if len(values) == 2: # match
metric, value = values
try:
value = float(value)
except ValueError:
continue
# Send metric as a gauge, if applicable
if metric in self.GAUGES:
metric_count += 1
metric_name = self.GAUGES[metric]
log.debug('Collecting gauge data for: {0}'.format(metric_name))
self.gauge(metric_name, value, dimensions=dimensions)
# Send metric as a rate, if applicable
if metric in self.RATES:
metric_count += 1
metric_name = self.RATES[metric]
log.debug('Collecting rate data for: {0}'.format(metric_name))
self.rate(metric_name, value, dimensions=dimensions)
if metric_count == 0:
if self.url[-5:] != '?auto':
self.url = '%s?auto' % self.url
self.log.warn("Assuming url was not correct. Trying to add ?auto suffix to the url")
self.check(instance)
else:
return services_checks.Status.DOWN,
"%s is DOWN, error: No metrics available.".format(service_check_name)
else:
log.debug("Collected {0} metrics for {1} Apache Web Server".format(apache_host,
metric_count))