commit 28fc63427406b4ee92e1dd6d11a9a98319377533 Author: Edward Marshall Date: Thu Sep 8 09:40:50 2016 +0100 intial commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..09cdc6b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.5-alpine + +RUN pip install prometheus_client requests + +ENV BIND_PORT 1234 +ENV IMAGES "prom/prometheus, prom/node-exporter" + +ADD . /usr/src/app +WORKDIR /usr/src/app + +CMD ["python", "hub_exporter.py"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..17ef315 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Infinity Works Ltd + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..85e8250 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# Prometheus Docker Hub Exporter + +Exposes metrics of container pulls and stars from the Docker Hub API, to a Prometheus compatible endpoint. + +## Configuration + +The image is setup to take two parameters from environment variables: +`BIND_PORT` The port you wish to run the container on, defaults to 1234 +`IMAGES` The images you wish to monitor, expected in the format "user/image1, user/image2". Can be across different dockerhub users. + +## Install and deploy + +Run manually from Docker Hub: +``` +docker run -d --restart=always -p 1234:1234 -e IMAGES="infinityworks/ranch-eye, infinityworks/prom-conf" infinityworks/docker-hub-exporter +``` + +Build a docker image: +``` +docker build -t . +docker run -d --restart=always -p 1234:1234 -e IMAGES="infinityworks/ranch-eye, infinityworks/prom-conf" +``` + +## Docker compose + +``` +docker-hub-exporter: + tty: true + stdin_open: true + expose: + - 1234:1234 + image: infinityworks/docker-hub-exporter +``` + +## Metrics + +Metrics will be made available on port 1234 by default + +``` +# HELP docker_hub_pull_count counter of docker_pulls from the public API +# TYPE docker_hub_pull_count counter +docker_hub_pull_count{image="prometheus",user="prom"} 5360660.0 +docker_hub_pull_count{image="node-exporter",user="prom"} 9668841.0 +# HELP docker_hub_star_count counter of docker_stars from the public API +# TYPE docker_hub_star_count counter +docker_hub_star_count{image="prometheus",user="prom"} 133.0 +docker_hub_star_count{image="node-exporter",user="prom"} 16.0 +``` + +## Metadata + diff --git a/hub_exporter.py b/hub_exporter.py new file mode 100644 index 0000000..788d1d7 --- /dev/null +++ b/hub_exporter.py @@ -0,0 +1,48 @@ +from prometheus_client import start_http_server +from prometheus_client.core import CounterMetricFamily, REGISTRY + +import json +import requests +import sys +import time +import os + + +class HubCollector(object): + + def collect(self): + images = os.getenv('IMAGES', default="thebsdbox/ovcli, rucknar/prom-conf").replace(' ','').split(",") + print("Starting exporter") + self._pull_metrics = CounterMetricFamily('docker_hub_pull_count', 'counter of docker_pulls from the public API', labels=["image", "user"]) + self._star_metrics = CounterMetricFamily('docker_hub_star_count', 'counter of docker_stars from the public API', labels=["image", "user"]) + + for image in images: + print("Getting JSON for " + image) + self._get_json(image) + print("Getting Metrics for " + image) + self._get_metrics() + print ("Metrics Updated for " + image) + + yield self._pull_metrics + yield self._star_metrics + + def _get_json(self, image): + print("Getting JSON Payload for " + image) + image_url = 'https://hub.docker.com/v2/repositories/{0}'.format(image) + print(image_url) + response = requests.get(image_url) + self._response_json = json.loads(response.content.decode('UTF-8')) + + + def _get_metrics(self): + image_name = self._response_json['name'] + user_name = self._response_json['user'] + self._pull_metrics.add_metric([image_name, user_name], value=self._response_json['pull_count']) + self._star_metrics.add_metric([image_name, user_name], value=self._response_json['star_count']) + + +if __name__ == '__main__': + start_http_server(int(os.getenv('BIND_PORT'))) + REGISTRY.register(HubCollector()) + + while True: time.sleep(1)