diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ef4ddff --- /dev/null +++ b/.dockerignore @@ -0,0 +1,157 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +.gitignore +Dockerfile +LICENSE +README.md +.circleci/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fffa5ed --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.6-alpine3.6 + +WORKDIR /usr/src/app + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD [ "python", "./app.py" ] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a31912c --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Example Prometheus Instrumentation for Python + +This is a quick example of how to instrument your Flask-based Python app +with the Python Prometheus client. + +This project is built with: + +- Python 3.6.x + +And is packaged as a Docker container. The two top level dependencies are: + +- Flask==0.12.2 +- prometheus-client==0.0.21 + +See the [requirements file](./requirements.txt) for more details. + +## Prometheus + +[Prometheus](https://prometheus.io/) is a +[Cloud Native](https://winderresearch.com/what-is-cloud-native/?utm_source=github&utm_medium=web&utm_content=link) +monitoring application. + +To instrument our Python code we need to manipulate the metrics each +time a new HTTP request is received. + +See [the application](./app.py) for more details. + +## Building + +This project is automatically built by Docker Automated Builds. + +To build manually: + +`docker build -t python-app .` + +## Running + +Simply open port 5000 when running as a container: + +`docker run -p 5000:5000 --name python-app philwinder/prometheus-python` \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..d07799f --- /dev/null +++ b/app.py @@ -0,0 +1,57 @@ +import random +import time + +from flask import Flask, render_template_string +from prometheus_client import generate_latest, REGISTRY, Counter, Gauge, Histogram + +app = Flask(__name__) + +# A counter to count the total number of HTTP requests +REQUESTS = Counter('http_requests_total', 'Total HTTP Requests (count)', ['method', 'endpoint']) + +# A gauge (i.e. goes up and down) to monitor the total number of in progress requests +IN_PROGRESS = Gauge('http_requests_inprogress', 'Number of in progress HTTP requests') + +# A histogram to measure the latency of the HTTP requests +TIMINGS = Histogram('http_requests_latency_seconds', 'HTTP request latency (seconds)') + + +# Standard Flask route stuff. +@app.route('/') +# Helper annotation to measure how long a method takes and save as a histogram metric. +@TIMINGS.time() +# Helper annotation to increment a gauge when entering the method and decrementing when leaving. +@IN_PROGRESS.track_inprogress() +def hello_world(): + REQUESTS.labels(method='GET', endpoint="/").inc() # Increment the counter + return 'Hello, World!' + + +@app.route('/slow') +@TIMINGS.time() +@IN_PROGRESS.track_inprogress() +def slow_request(): + REQUESTS.labels(method='GET', endpoint="/slow").inc() + v = random.random() + time.sleep(v) + return render_template_string('