Python Microservice: Monitoring Stack

Both Prometheus and Grafana are compatible with microservice applications, integrating Prometheus with Flask is straightforward to provide performance and monitoring metrics.

Here I will update the docker-compose to add Prometheus and Grafana as services, then add Prometheus metrics in both order and user application code by importing PrometheusMetrics from the prometheus_flask_exporter module, which is used to expose Prometheus metrics for the Flask application. Then initialize Prometheus metrics with metrics = PrometheusMetrics(app). Use @metrics.counter('get_orders_count', 'Count of calls to the get_orders endpoint') to define a Prometheus counter metric that increments each time the get_orders endpoint is called.

Import os to enable environment variable for Logstash host, logstash_host = os.getenv('LOGSTASH_HOST', 'localhost') to fetch the Logstash host from environment variables, defaulting to localhost.

  # Folder structure
  /06-with-monitoringstack
  ├── api_gateway
  │   ├── api_gateway.py
  │   └── Dockerfile
  ├── docker-compose.yml
  ├── logstash.conf
  ├── order_service
  │   ├── Dockerfile
  │   ├── order_service.py
  ├── prometheus.yaml
  └── user_service
      ├── Dockerfile
      └── user_service.py

  # add Prometheus and Grafana in docker-compose.yaml
  version: '3'
  services:
    prometheus:
      image: prom/prometheus
      volumes:
        - ./prometheus.yml:/etc/prometheus/prometheus.yml
      ports:
        - "9090:9090"
    grafana:
      image: grafana/grafana
      ports:
        - "3000:3000"

  # create prometheus.yml for Prometheus configration
  # vim prometheus.yml
  global:
    scrape_interval: 15s

  scrape_configs:
    - job_name: 'flask'
      static_configs:
        - targets: ['user-service:5001', 'order-service:5002']

  # add Monitoring logic into python code 

  # order_service.py
  import logging
  import requests
  from flask import Flask, jsonify
  from pygelf import GelfUdpHandler
  from prometheus_flask_exporter import PrometheusMetrics
  import os

  app = Flask(__name__)
  metrics = PrometheusMetrics(app)

  @app.route('/orders')
  def get_orders():
      orders = [
          {'id': 1, 'item': 'Laptop', 'price': 1200},
          {'id': 2, 'item': 'Phone', 'price': 800}
      ]
      app.logger.info("Fetched order data")
      return jsonify(orders)

  def register_service():
      payload = {
          "ID": "order-service",
          "Name": "order-service",
          "Address": "order-service",
          "Port": 5002
      }
      response = requests.put('http://consul:8500/v1/agent/service/register', json=payload)
      if response.status_code == 200:
          app.logger.info("Order service registered successfully")
      else:
          app.logger.error("Failed to register order service")

  if __name__ == '__main__':
      # Configure logging
      logstash_host = os.getenv('LOGSTASH_HOST', 'localhost')
      handler = GelfUdpHandler(host=logstash_host, port=12201)
      app.logger.addHandler(handler)
      app.logger.setLevel(logging.INFO)

      register_service()
      app.run(host='0.0.0.0', port=5002)


  # user_service.py
  import logging
  import requests
  from flask import Flask, jsonify
  from pygelf import GelfUdpHandler
  from prometheus_flask_exporter import PrometheusMetrics
  import os

  app = Flask(__name__)
  metrics = PrometheusMetrics(app)

  @app.route('/users')
  def get_users():
      users = [
          {'id': 1, 'name': 'Alice'},
          {'id': 2, 'name': 'Bob'}
      ]
      app.logger.info("Fetched user data")
      return jsonify(users)

  def register_service():
      payload = {
          "ID": "user-service",
          "Name": "user-service",
          "Address": "user-service",
          "Port": 5001
      }
      response = requests.put('http://consul:8500/v1/agent/service/register', json=payload)
      if response.status_code == 200:
          app.logger.info("User service registered successfully")
      else:
          app.logger.error("Failed to register user service")

  if __name__ == '__main__':
      # Configure logging
      logstash_host = os.getenv('LOGSTASH_HOST', 'localhost')
      handler = GelfUdpHandler(host=logstash_host, port=12201)
      app.logger.addHandler(handler)
      app.logger.setLevel(logging.INFO)

      register_service()
      app.run(host='0.0.0.0', port=5001)

  

Now Run docker-compose to bring all containers up and running. Should see all services with Prometheus and Grafana.

  docker-compose up --build

  Creating 06-with-monitoringstack_api-gateway_1   ... done
  Creating 06-with-monitoringstack_order-service_1 ... done
  Creating 06-with-monitoringstack_user-service_1  ... done
  Creating 06-with-monitoringstack_kibana_1        ... done
  Creating 06-with-monitoringstack_grafana_1       ... done
  Creating 06-with-monitoringstack_logstash_1      ... done
  Creating 06-with-monitoringstack_prometheus_1    ... done
  Creating 06-with-monitoringstack_elasticsearch_1 ... done
  Creating 06-with-monitoringstack_consul_1        ... done
  

Verify Prometheus and Grafana

Access Grafana via http://localhost:3000, log in with admin/admin.

Add Prometheus as a Data Source in Grafana by setting the URL to http://localhost:9090 and save.

Create Dashboards in Grafana to use the Prometheus data source to visualize metrics from user-service and order-service.

image tooltip here image tooltip here

Conclusion

Now we can enable monitoring with Prometheus and Grafana.

In the next post, I will see how to deploy our Python Flask microservice into Kubernetes.

Welcome to Zack's Blog

Join me for fun journey about ##AWS ##DevOps ##Kubenetes ##MLOps

  • Latest Posts