Skip to content

Commit

Permalink
Merge pull request #11 from cgroschupp/feat/python3
Browse files Browse the repository at this point in the history
remove python2 support and cleanup
  • Loading branch information
stuart-warren authored Feb 7, 2020
2 parents a95a947 + e8c3a88 commit 073c3b5
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 139 deletions.
33 changes: 7 additions & 26 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,13 @@
FROM alpine:latest
FROM python:3.7-alpine

# Adds testing package to repositories
# Install needed packages. Notes:
# * build-base: used so we include the basic development packages (gcc)
# * python-dev: are used for gevent e.g.
# * bash: so we can access /bin/bash
RUN echo "@testing http://dl-4.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
&& apk add --update \
musl \
build-base \
bash \
git \
python \
python-dev \
py-pip \
&& pip install --upgrade pip \
&& rm /var/cache/apk/*
WORKDIR /usr/src/app

# make some useful symlinks that are expected to exist
RUN cd /usr/bin \
&& ln -sf easy_install-2.7 easy_install \
&& ln -sf python2.7 python \
&& ln -sf python2.7-config python-config \
&& ln -sf pip2.7 pip
COPY requirements.txt ./

RUN pip install prometheus-client==0.0.14
RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 9184
COPY nexus_exporter.py /nexus_exporter.py

ENTRYPOINT ["/nexus_exporter.py"]
EXPOSE 9184

ENTRYPOINT ["/nexus_exporter.py"]
229 changes: 117 additions & 112 deletions nexus_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@
import json
import time
import base64
try:
import urllib2
from urlparse import urlparse
from urllib2 import URLError, HTTPError
except ImportError:
# Python 3
import urllib.request as urllib2
from urllib.parse import urlparse
from urllib.error import URLError, HTTPError
import logging
import urllib.request as urllib2
from urllib.parse import urlparse
from urllib.error import URLError, HTTPError
from prometheus_client import start_http_server
from prometheus_client.core import GaugeMetricFamily, REGISTRY
import argparse

LOG = logging.getLogger('nexus-exporter')
logging.basicConfig(level=logging.INFO)


def valid_url(string):
"""Validate url input argument.
Expand All @@ -39,56 +37,72 @@ def parse():
parser = argparse.ArgumentParser(
description='Export Prometheus metrics for Sonatype Nexus > 3.6')
parser.add_argument(
'--host', metavar='HOST',
'--host',
metavar='HOST',
type=valid_url,
help='address with port where Nexus is available. Defaults to\
http://localhost:8081',
default=os.environ.get("NEXUS_HOST", "http://localhost:8081")
)
parser.add_argument(
"--password", "-p", help="admin password",
default=os.environ.get("NEXUS_ADMIN_PASSWORD", "admin123")
)
parser.add_argument(
"--user", "-u", help="Nexus user name, defaults to admin",
default=os.environ.get("NEXUS_USERNAME", "admin")
)
default=os.environ.get("NEXUS_HOST", "http://localhost:8081"))
parser.add_argument("--password",
"-p",
help="admin password",
default=os.environ.get("NEXUS_ADMIN_PASSWORD",
"admin123"))
parser.add_argument("--user",
"-u",
help="Nexus user name, defaults to admin",
default=os.environ.get("NEXUS_USERNAME", "admin"))
parser.add_argument("--port",
help="Exporter port: default 9184",
default=9184)
return parser.parse_args()


class NexusCollector(object):
def __init__(self, target, user, password):
self._target = target.rstrip("/")
self._auth = base64.standard_b64encode('%s:%s' % (user, password))
auth_string = '%s:%s' % (user, password)
self._auth = base64.standard_b64encode(auth_string.encode())
self._info = {}
self._data = {}

def collect(self):
# make requests
nexus_up = True
try:
self._request_data()
except HTTPError as err:
if err.code == 401:
fatal('Authentication failure, attempting to restart')
except URLError as err:
fatal(err)
LOG.error('Authentication failure, please check \
username/password')
nexus_up = False
except URLError as e:
LOG.error('unable to fetch data from metric endpoint: %s', e)
nexus_up = False

yield GaugeMetricFamily('nexus_up',
'Whether the Nexus server is up.',
value=nexus_up)

if not nexus_up:
return

i = self._info['system-runtime']
yield GaugeMetricFamily(
'nexus_processors_available',
'Available Processors', value=i['availableProcessors'])
yield GaugeMetricFamily(
'nexus_free_memory_bytes',
'Free Memory (bytes)', value=i['freeMemory'])
yield GaugeMetricFamily(
'nexus_total_memory_bytes',
'Total Memory (bytes)', value=i['totalMemory'])
yield GaugeMetricFamily(
'nexus_max_memory_bytes',
'Max Memory (bytes)', value=i['maxMemory'])
yield GaugeMetricFamily(
'nexus_threads_used',
'Threads Used', value=i['threads'])
yield GaugeMetricFamily('nexus_processors_available',
'Available Processors',
value=i['availableProcessors'])
yield GaugeMetricFamily('nexus_free_memory_bytes',
'Free Memory (bytes)',
value=i['freeMemory'])
yield GaugeMetricFamily('nexus_total_memory_bytes',
'Total Memory (bytes)',
value=i['totalMemory'])
yield GaugeMetricFamily('nexus_max_memory_bytes',
'Max Memory (bytes)',
value=i['maxMemory'])
yield GaugeMetricFamily('nexus_threads_used',
'Threads Used',
value=i['threads'])

i = self._info['system-filestores']
for fsname, details in i.iteritems():
Expand Down Expand Up @@ -119,59 +133,61 @@ def collect(self):
yield fas

i = self._data['gauges']
yield GaugeMetricFamily(
'nexus_jvm_memory_heap_committed_bytes',
'', value=i['jvm.memory.heap.committed']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_heap_init_bytes',
'', value=i['jvm.memory.heap.init']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_heap_max_bytes',
'', value=i['jvm.memory.heap.max']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_heap_used_bytes',
'', value=i['jvm.memory.heap.used']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_heap_committed_bytes',
'',
value=i['jvm.memory.heap.committed']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_heap_init_bytes',
'',
value=i['jvm.memory.heap.init']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_heap_max_bytes',
'',
value=i['jvm.memory.heap.max']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_heap_used_bytes',
'',
value=i['jvm.memory.heap.used']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_nonheap_committed_bytes',
'', value=i['jvm.memory.non-heap.committed']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_nonheap_init_bytes',
'', value=i['jvm.memory.non-heap.init']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_nonheap_max_bytes',
'', value=i['jvm.memory.non-heap.max']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_nonheap_used_bytes',
'', value=i['jvm.memory.non-heap.used']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_total_committed_bytes',
'', value=i['jvm.memory.total.committed']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_total_init_bytes',
'', value=i['jvm.memory.total.init']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_total_max_bytes',
'', value=i['jvm.memory.total.max']['value'])
yield GaugeMetricFamily(
'nexus_jvm_memory_total_used_bytes',
'', value=i['jvm.memory.total.used']['value'])
yield GaugeMetricFamily(
'nexus_jvm_uptime_seconds',
'', value=i['jvm.vm.uptime']['value']/1000.0)
'',
value=i['jvm.memory.non-heap.committed']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_nonheap_init_bytes',
'',
value=i['jvm.memory.non-heap.init']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_nonheap_max_bytes',
'',
value=i['jvm.memory.non-heap.max']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_nonheap_used_bytes',
'',
value=i['jvm.memory.non-heap.used']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_total_committed_bytes',
'',
value=i['jvm.memory.total.committed']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_total_init_bytes',
'',
value=i['jvm.memory.total.init']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_total_max_bytes',
'',
value=i['jvm.memory.total.max']['value'])
yield GaugeMetricFamily('nexus_jvm_memory_total_used_bytes',
'',
value=i['jvm.memory.total.used']['value'])
yield GaugeMetricFamily('nexus_jvm_uptime_seconds',
'',
value=i['jvm.vm.uptime']['value'] / 1000.0)

i = self._data['meters']
et = GaugeMetricFamily(
'nexus_events_total', 'Nexus Events Count', labels=['level'])
et = GaugeMetricFamily('nexus_events_total',
'Nexus Events Count',
labels=['level'])
et.add_metric(['trace'], i['metrics.trace']['count'])
et.add_metric(['debug'], i['metrics.debug']['count'])
et.add_metric(['info'], i['metrics.info']['count'])
et.add_metric(['warn'], i['metrics.warn']['count'])
et.add_metric(['error'], i['metrics.error']['count'])
yield et

hr = GaugeMetricFamily(
'nexus_webapp_http_response_total',
'Nexus Webapp HTTP Response Count', labels=['code'])
hr = GaugeMetricFamily('nexus_webapp_http_response_total',
'Nexus Webapp HTTP Response Count',
labels=['code'])
hr.add_metric(
['1xx'],
i['org.eclipse.jetty.webapp.WebAppContext.1xx-responses']['count'])
Expand All @@ -190,19 +206,17 @@ def collect(self):
yield hr

i = self._data['timers']
hq = GaugeMetricFamily(
'nexus_webapp_http_request_total',
'Nexus Webapp HTTP Request Count', labels=['method'])
hq = GaugeMetricFamily('nexus_webapp_http_request_total',
'Nexus Webapp HTTP Request Count',
labels=['method'])
hq.add_metric(
['connect'],
i[
'org.eclipse.jetty.webapp.WebAppContext.connect-requests'
]['count'])
i['org.eclipse.jetty.webapp.WebAppContext.connect-requests']
['count'])
hq.add_metric(
['delete'],
i[
'org.eclipse.jetty.webapp.WebAppContext.delete-requests'
]['count'])
i['org.eclipse.jetty.webapp.WebAppContext.delete-requests']
['count'])
hq.add_metric(
['get'],
i['org.eclipse.jetty.webapp.WebAppContext.get-requests']['count'])
Expand All @@ -214,51 +228,42 @@ def collect(self):
i['org.eclipse.jetty.webapp.WebAppContext.move-requests']['count'])
hq.add_metric(
['options'],
i[
'org.eclipse.jetty.webapp.WebAppContext.options-requests'
]['count'])
hq.add_metric(
['other'],
i[
'org.eclipse.jetty.webapp.WebAppContext.other-requests'
]['count'])
i['org.eclipse.jetty.webapp.WebAppContext.options-requests']
['count'])
hq.add_metric([
'other'
], i['org.eclipse.jetty.webapp.WebAppContext.other-requests']['count'])
hq.add_metric(
['post'],
i['org.eclipse.jetty.webapp.WebAppContext.post-requests']['count'])
hq.add_metric(
['put'],
i['org.eclipse.jetty.webapp.WebAppContext.put-requests']['count'])
hq.add_metric(
['trace'],
i[
'org.eclipse.jetty.webapp.WebAppContext.trace-requests'
]['count'])
hq.add_metric([
'trace'
], i['org.eclipse.jetty.webapp.WebAppContext.trace-requests']['count'])
yield hq

def _mount_point(self, description):
return description.split('(')[0].strip()

def _request_data(self):
info_request = urllib2.Request(
"{0}/service/rest/atlas/system-information".format(
self._target))
"{0}/service/rest/atlas/system-information".format(self._target))
info_request.add_header("Authorization", "Basic %s" % self._auth)
self._info = json.loads(urllib2.urlopen(info_request).read())

data_request = urllib2.Request("{0}/service/metrics/data".format(
self._target))
self._target))
data_request.add_header("Authorization", "Basic %s" % self._auth)
self._data = json.loads(urllib2.urlopen(data_request).read())


def fatal(msg):
print(msg)
os._exit(1) # hard exit without throwing exception

if __name__ == "__main__":
print("starting...")
args = parse()
LOG.info('starting nexus exporter on port %s' % args.port)

REGISTRY.register(NexusCollector(args.host, args.user, args.password))
start_http_server(9184)
start_http_server(args.port)
while True:
time.sleep(1)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
prometheus-client==0.0.14
prometheus-client==0.7.1

0 comments on commit 073c3b5

Please sign in to comment.