1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vol.1】Python特化のOpenTelemetry+LGTMスタック最小構成

1
Posted at

1. はじめに

OpenTelemetryの学習にあたり、公式デモを、ようやく動かせるようになったので、それを忘れないうちに、Python(Flask/Locust)特化のシンプルな最小構成環境を作ってみました。
手作業を排除し、EC2上にインフラ構築から自動監視までをTerraformで自動作成します。

今回は 【Vol.1】環境構築編 として、まずは動かすことに特化しています。
自分自身の学習記録の備忘録としての意味合いもあります。

image.png

2. Grafana Labs公式「LGTMスタック」デモとは、

本環境は、Grafana Labs公式の OpenTelemetry Demo をベースにしています。公式デモは、モダンな可観測性(Observability)の標準である 「LGTMスタック」 を手軽に体験できる素晴らしい環境です。

📊 LGTMスタックの構成要素

コンポーネント 役割
Loki ログを集約・検索する軽量なログ管理システム
Grafana 収集データを1つにまとめて可視化するダッシュボード
Tempo リクエストの経路を追跡する分散トレーシング
Mimir / Prometheus システム状態(CPUやリクエスト数など)を蓄積するメトリクス

「LGTMスタック」イメージのみ流用し、アプリ側を 「Python(Flask/Locust)の最小構成」 に絞り込み、ファイル構成、設定内容を理解しやすくしました。

3. 今回のチャレンジと「あえてやらなかったこと」

今回の最大の目的は、 「必要な部分だけを切り出して、自分なりにカスタマイズしやすい環境を作る」 ことです。

具体的には、以下の要素に絞って手を動かし、理解を深めました。

  • Grafanaでの可視化の仕組み
    • ダッシュボードが「何を、どう表示しているか」の整理
    • PromQLや関数を用いたグラフ描画の分析
  • OpenTelemetry(メトリクス中心)の挙動確認
    • アプリからデータが「どのように出力されるか」の観察
    • 負荷(Locust)をかけたときのメトリクス変動の観測

「あえてやらなかったこと」は、LGTMスタック各コンポーネント(Loki, Tempo, Mimir, OTel Collector)間の内部接続や詳細設定は公式デモの構成を流用しています。

4. 技術スタック

本環境で使用している技術スタックは以下の通りです。

  • インフラ(IaC):Terraform
  • クラウド:AWS (VPC, Subnet, Security Group, EC2 [Amazon Linux 2023])
  • コンテナ:Docker / Docker Compose
  • アプリケーション:Python 3.11 / Flask (Webアプリ) / Locust (負荷テストツール)
  • 可観測性(Observability)エコシステム:
    • データ収集:OpenTelemetry
    • 可視化:Grafana
    • メトリクス蓄積:Prometheus
    • ログ蓄積:Loki
    • 分散トレーシング:Tempo

ディレクトリ構成

本環境の全体構成は以下の通りです。
このデータセットは、GitHubリポジトリ に登録しています。

├── ENV_1011/                         # main.tfの構築・プロビジョニング時に使用される環境データ
│   ├── my-dashboards/                # Grafanaのダッシュボード設定を格納
│   │   └── grafana-dashboard-python-metrics.json
│   ├── python/                       # OpenTelemetryによるメトリクス生成を組み込んだアプリ
│   │   ├── app.py                    # Flaskアプリケーション本体
│   │   └── locustfile.py             # 負荷試験用のLocustスクリプト
│   ├── services/                     # EC2上で常時稼働させるsystemd用の設定ファイル
│   │   ├── flask-app.service
│   │   └── locust-worker.service
│   ├── clear-defaults.yaml           # 各種環境の初期設定をクリア・調整するための設定
│   ├── my-dashboard-config.yaml      # Grafanaダッシュボードのプロバイダー設定
│   └── run-lgtm.sh                   # LGTMスタック(Grafana等)を起動・制御するスクリプト
└── devops_1011/                      # 構築・自動化用コード
    ├── scripts/
    │   └── setup.sh                  # お試し構築・初期セットアップ用スクリプト
    └── terraform/                    # IaC(Infrastructure as Code)関連コード
        ├── main.tf                   # AWS EC2インフラやネットワークの定義
        └── output.tf                 # 構築後のパブリックIP等の出力定義

各ディレクトリ・ファイルの役割

インフラ自動化・構築 (./devops_1011/)

Terraformを用いて、AWSのEC2上にインフラ環境を自動構築します。

image.png

アプリケーション & 自動監視環境 ( ./ENV_1011/ )

main.tf を実行し、EC2インスタンス起動後に、環境構築/python実行で必要なファイルを格納しています。

image.png

5. システム構成

image.png

今回はGrafana Labs公式デモ版のコンテナイメージ(grafana/otel-lgtm)をベースに使用しているため、OpenTelemetry Collector部や各バックエンド(Prometheus / Tempo / Loki / Pyroscope)の内部構成はそちらに依存しています。

このシステムに対して、自作した「Python Web App (Flask)」と「負荷生成器(Locust)」を接続し、EC2インスタンス(t3.small)内でsystemdとしてバックグラウンド実行させています。

インフラ構築や環境配備の自動化を図るために、Terraform でAWSリソースの自動生成を行い、EC2のUser DataをトリガーにGitHub・Docker Hubと連携してデプロイを自動化しています。

  • GitHub:最新のソースコード(app.py / locustfile.py)を自動取得
  • Docker Hub:可視化基盤のコンテナイメージ(grafana/otel-lgtm)をプル

🔄 各コンポーネントの役割

image.png

6. メトリクス

ダッシュボードで可視化したメトリクスは以下の通りです。
Locustの負荷変動に応じて、これらの値も変動します。

image.png

具体的なコードについては、末尾の 【付録:環境構築用コード】 にある「grafana-dashboard-python-metrics.json」を参照してください。

今回の構成ではメトリクス収集に特化しており、LokiやTempoへのデータ送信に必要な機能実装は行わなかったので、 ログ、トレース の内容は見られません。

7.デプロイ手順

インフラのプロビジョニングからアプリのデプロイ、監視の有効化まで、Terraformで自動化しています。

1. 環境変数の設定

ローカル環境に自身のAWSの認証情報(アクセスキーなど)をセットします。

2. Terraformの実行

terraform apply を実行します。AWS上にVPC、セキュリティグループ、EC2(Amazon Linux 2023)が自動生成されます。
※具体的なIaCコードは末尾の 【付録:環境構築用コード】 を参照。

3. user_dataによる完全自動セットアップ

EC2の起動時、user_dataがバックグラウンドで以下の処理を全自動で実行します。

  1. GitのSparse Checkout(部分チェックアウト) を使い、リポジトリから必要なディレクトリ(ENV_1011)のみダウンロード。
  2. Docker / Docker Compose のインストールと起動。
  3. 公式スクリプト(run-lgtm.sh)によるLGTMスタックコンテナ起動。
  4. Python 3.11環境の構築と、必要ライブラリ(Flask, OpenTelemetry SDK, Locustなど)のインストール。
  5. Pythonスクリプトの配置、およびsystemdへのサービス登録と自動起動。

4. Grafanaへのアクセス

terraform apply 完了後、数分待つだけでセットアップが完了します。出力されたパブリックIPの3000番ポート(http://<EC2のパブリックIP>:3000)へアクセスすれば、すぐに完成したダッシュボードを確認できます。

詳細手順は、こちらを参照

URL指定(Grafana-GUI)

terraform apply 完了後、以下の様にパブリックIPが出力されます。

ec2_private_ip = "10.0.1.206"
ec2_public_ip = "3.112.205.128"

上記のケースでは、以下のURL に2~3分待ってアクセスします。
http://3.112.205.128:3000

ダッシュボード選択

以下の様に、Grafana からダッシュボード選択を行います。

image.png

メニュー選択

表示期間を「⏱ Last 5 minutes」に切り替えて、10分ほど待つと、以下のようなデータが見られるようになります。

image.png

8. おわりに

今回の取り組みを通じ、OpenTelemetryの強力さとLGTMスタックによる監視基盤の構築方法を深く学ぶことができました。
手間の多い手動構築(SSH、クローン、権限変更、サービス登録など)を、Terraformの user_data と Gitの Sparse Checkout で自動化し、「コマンドで環境構築」する面白味を実感できました。

周辺技術での学び

環境コード化にあたり、監視以外の実用的なスキルも習得できました。

  • Locustによる動的負荷試験:リクエストを変動させ、意図的にメトリクスの波(トレンド)を作る手法
  • Terraformの user_data:EC2起動時のプロビジョニングを完全自動化する実務的な手法

9. 今後の展望

今回は【Vol.1】として「最小構成で動かす」ことを最優先しました。このベース環境を活かし、以下の要素にも挑戦する予定です。(あくまでも予定です)

  • 監視基盤の自作化:公式デモの流用を脱却し、各コンポーネントとCollector間の接続・設定をイチから自作する
  • 自動制御の組み込み:各バックエンドのデータをシェルスクリプト等で定期取得し、異常を自動検知する仕組みの実装。
  • 構成管理の高度化:user_data(シェルスクリプト)で行っているアプリ配置やサービス登録を、Ansibleによる管理へ移行する。
  • オブザーバビリティの完全化:今回はメトリクスのみのだった構成にLoki(ログ)とTempo(トレース)の実装を本格追加し、「3つの柱」を可視化できる環境の構築。

10.付録:環境構築用コード

GitHubレポジトリ に登録しています

./terraform/main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

# 1. VPC(仮想ネットワーク)の作成
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = {
    Name = "study-vpc"
  }
}

# 2. パブリックサブネットの作成
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  map_public_ip_on_launch = true # 起動時にパブリックIPを自動割り当て
  tags = {
    Name = "study-public-subnet"
  }
}

# 3. インターネットゲートウェイの作成(外の世界と繋ぐ窓口)
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "study-igw"
  }
}

# 4. ルートテーブルの作成と紐付け(ネットへの道を登録)
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }
  tags = {
    Name = "study-public-rt"
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# =================================================================================
# 1. セキュリティグループの定義
# =================================================================================
resource "aws_security_group" "ec2" {
  name        = "study-ec2-sg"
  description = "Security Group for OpenTelemetry and App Server"
  vpc_id      = aws_vpc.main.id # ※環境に合わせてVPC IDの変数名を調整してください

  # -------------------------------------------------------------------------------
  # 各種アプリケーション・可観測性ツール用のインバウンドルール(dynamicブロックで一括管理)
  # -------------------------------------------------------------------------------
  dynamic "ingress" {
    for_each = {
      22    = "SSH"
      3000  = "Grafana UI"
      16686 = "Jaeger UI"
      9090  = "Prometheus UI"
      3100  = "Loki"
      8000  = "Python Web App"
      9464  = "OpenTelemetry Prometheus Exporter"
      5000  = "Python App (Flask)"
      4317  = "OpenTelemetry (OTLP/gRPC)"
      4318  = "OpenTelemetry (OTLP/HTTP)"
      8080  = "OpenTelemetry Demo Web & Grafana"
    }

    content {
      description = ingress.value
      from_port   = ingress.key
      to_port     = ingress.key
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
  }

  # -------------------------------------------------------------------------------
  # 【超重要】EC2同士(VPC内部)の全通信を許可するルール
  # -------------------------------------------------------------------------------
  ingress {
    description = "VPC Internal All Traffic"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"            # すべてのプロトコルを許可
    cidr_blocks = ["10.0.0.0/16"] # VPC内部のIPアドレスからの通信をすべて許可
  }

  # -------------------------------------------------------------------------------
  # インターネットへの外向き通信をすべて許可(重複を排除して1つにスッキリ整理)
  # -------------------------------------------------------------------------------
  egress {
    description = "Allow all outbound traffic"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# =================================================================================
# 2. SSH接続用のキーペアを自動生成
# =================================================================================
resource "tls_private_key" "keygen" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "keypair" {
  key_name   = "study-key"
  public_key = tls_private_key.keygen.public_key_openssh
}

# 生成された秘密鍵(Terra Termで使う.pemファイル)をローカルに保存
resource "local_file" "private_key" {
  content  = tls_private_key.keygen.private_key_pem
  filename = "${path.module}/study-key.pem"
}

# =================================================================================
# 3. AWSから自動で最新のAmazon Linux 2023 AMI IDを取得
# =================================================================================
data "aws_ssm_parameter" "amzn_linux_2023" {
  name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64"
}

# =================================================================================
# 4. EC2インスタンスの作成(GitHubパブリック方式・完全自動化版)
# =================================================================================
resource "aws_instance" "app_server" {
  ami           = data.aws_ssm_parameter.amzn_linux_2023.value
  instance_type = "t3.small"

  subnet_id              = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.ec2.id]
  key_name               = aws_key_pair.keypair.key_name

  # ルートディスク容量を30GB(無料枠の最大値)に増やす設定
  root_block_device {
    volume_size = 30
    volume_type = "gp3"
  }

  tags = {
    Name = "study-ec2-1"
  }

  # ===============================================================================
  # 【完全自動化】初期化シェルスクリプト(user_data)
  # ===============================================================================
  user_data = <<-EOF
    #!/bin/bash
    # エラーが発生したら即座にスクリプトを終了させる設定
    set -euo pipefail

    echo "=========================================================="
    echo "=== 1. GitHubから特定のディレクトリ(ENV_1011)のみを取得 ==="
    echo "=========================================================="
    dnf install -y git
    sleep 5

    mkdir -p /opt/deploy_data
    cd /opt/deploy_data

    # Sparse Checkout(部分チェックアウト)の設定
    git init
    git remote add origin https://github.com/wata123-t/deploy_data
    git config core.sparseCheckout true
    echo "ENV_1011/" >> .git/info/sparse-checkout

    # データの引っ張りと移動
    git pull origin main
    cd ENV_1011

    echo "=========================================================="
    echo "=== 2. Docker & Docker Compose のインストールと起動 ==="
    echo "=========================================================="
    dnf install -y docker
    sleep 5
    systemctl enable --now docker

    # Docker Compose V2 のインストール
    mkdir -p /usr/local/lib/docker/cli-plugins/
    curl -SL https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
    chmod +x /usr/local/lib/docker/cli-plugins/docker-compose

    echo "=========================================================="
    echo "=== 3. Grafana Labs公式「LGTMスタック」デモの実行 ==="
    echo "=========================================================="
    # すでにGit側で権限を付与していますが、念のため再付与して実行
    chmod +x ./run-lgtm.sh
    ./run-lgtm.sh
    sleep 10

    echo "=========================================================="
    echo "=== 4. Python 3.11 & 開発ツールのインストール ==="
    echo "=========================================================="
    dnf install -y python3.11 python3.11-pip python3.11-devel gcc
    sleep 10

    echo "=========================================================="
    echo "=== 5. 必要なPythonライブラリの一括インストール ==="
    echo "=========================================================="
    python3.11 -m pip install --upgrade pip
    sleep 10
    python3.11 -m pip install flask opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp opentelemetry-instrumentation-flask opentelemetry-instrumentation-system-metrics locust
    sleep 10

    echo "=========================================================="
    echo "=== 6. アプリケーションフォルダの作成とファイルのコピー ==="
    echo "=========================================================="
    mkdir -p /opt/script/python/app

    # GitHubから落としてきた相対パスからファイルをコピー
    cp "./python/app.py" /opt/script/python/app/app.py
    cp "./python/locustfile.py" /opt/script/python/locustfile.py

    echo "=========================================================="
    echo "=== 7. 各種サービス(systemd)ファイルの配置と起動 ==="
    echo "=========================================================="
    cp "./services/flask-app.service" /etc/systemd/system/flask-app.service
    cp "./services/locust-worker.service" /etc/systemd/system/locust-worker.service

    systemctl daemon-reload
    systemctl enable --now flask-app locust-worker

    echo "=========================================================="
    echo "=== すべてのセットアップ処理が正常に完了しました! ==="
    echo "=========================================================="
  EOF
}
./terraform/output.tf
# =================================================================================
# 5. アウトプット(接続用IPアドレスの表示)
# =================================================================================
output "ec2_public_ip" {
  value       = aws_instance.app_server.public_ip
  description = "起動したEC2のパブリックIPアドレスです"
}

output "ec2_private_ip" {
  value       = aws_instance.app_server.private_ip
  description = "EC2のプライベートIPアドレスです"
}
./my-dashboards/grafana-dashboard-python-metrics.json
{
  "annotations": {
    "list": [
      {
        "builtIn": 1,
        "datasource": {
          "type": "datasource",
          "uid": "grafana"
        },
        "enable": true,
        "hide": true,
        "iconColor": "rgba(0, 211, 255, 1)",
        "name": "Annotations & Alerts",
        "target": {
          "limit": 100,
          "matchAny": false,
          "tags": [],
          "type": "dashboard"
        },
        "type": "dashboard"
      }
    ]
  },
  "description": "Dashboard for **Python** metrics with OpenTelemetry instrumentation",
  "editable": true,
  "fiscalYearStartMonth": 0,
  "gnetId": 18812,
  "graphTooltip": 0,
  "links": [
    {
      "asDropdown": false,
      "icon": "info",
      "includeVars": false,
      "keepTime": false,
      "tags": [],
      "targetBlank": false,
      "title": "Semantic Conventions: 1.20.0 - 1.22.0",
      "tooltip": "multiple versions of the semantic conventions are supported using 'or' and regex queries",
      "type": "link",
      "url": "https://github.com/open-telemetry/semantic-conventions/blob/main/schemas/1.20.0"
    }
  ],
  "liveNow": false,
  "panels": [
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "HTTP server request rate",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisBorderShow": false,
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 25,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "insertNulls": false,
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "reqps"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 8,
        "x": 0,
        "y": 0
      },
      "id": 51,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by (instance) (rate({__name__=~\"http_server_request_duration_seconds_count|http_server_request_duration_count|http_server_duration_seconds_count|http_server_duration_count|http_server_duration_milliseconds_count|http_server_requests_milliseconds_count|http_server_requests_count|http_server_requests_seconds_count\", job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))",
          "instant": false,
          "legendFormat": "__auto",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Rate",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "HTTP server error ratio - ratio of requests that return 5xx",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisBorderShow": false,
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 25,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "insertNulls": false,
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "percentunit"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 8,
        "x": 8,
        "y": 0
      },
      "id": 50,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "(sum(rate(http_server_duration_milliseconds_count{http_status_code=~\"5..\"}[$__rate_interval])) / sum(rate(http_server_duration_milliseconds_count[$__rate_interval]))*1) or on() vector(0)",
          "instant": false,
          "legendFormat": "__auto",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Error %",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "95th percentile of HTTP server request duration in seconds",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisBorderShow": false,
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 25,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "insertNulls": false,
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "s"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 8,
        "w": 8,
        "x": 16,
        "y": 0
      },
      "id": 52,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "(histogram_quantile(0.95, sum by(le, instance) (rate({__name__=~\"http_server_request_duration_seconds_bucket|http_server_request_duration_bucket|http_server_duration_seconds_bucket|http_server_duration_bucket|http_server_requests_seconds_bucket\", job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))))\nor\n(histogram_quantile(0.95, sum by(le, instance) (rate({__name__=~\"http_server_duration_milliseconds_bucket|http_server_requests_milliseconds_bucket|http_server_requests_bucket\", job=~\"$job\", instance=~\"$instance\"}[$__rate_interval]))) / 1000)\n",
          "instant": false,
          "legendFormat": "{{instance}}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Duration (95%)",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "CPU utilization for the whole system",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisBorderShow": false,
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 25,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "insertNulls": false,
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "percentunit"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 7,
        "w": 13,
        "x": 0,
        "y": 8
      },
      "id": 38,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "multi",
          "sort": "desc"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "process_cpu_utilization_ratio",
          "legendFormat": "{{instance}}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "CPU utilization",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "Used heap memory / heap memory limit ",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisBorderShow": false,
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 25,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "insertNulls": false,
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "bytes"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 7,
        "w": 11,
        "x": 13,
        "y": 8
      },
      "id": 30,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "multi",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "process_memory_usage_bytes",
          "legendFormat": "{{instance}}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Heap Memory utilization",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "Percentage of time spend for garbage collection pauses",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisBorderShow": false,
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "bar",
            "fillOpacity": 25,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "insertNulls": false,
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              }
            ]
          },
          "unit": "short"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 7,
        "w": 13,
        "x": 0,
        "y": 15
      },
      "id": 46,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "sum by (instance) (rate(cpython_gc_collections_total[$__rate_interval]))*60",
          "hide": false,
          "legendFormat": "__auto",
          "range": true,
          "refId": "B"
        }
      ],
      "title": "Garbage Collection",
      "type": "timeseries"
    },
    {
      "datasource": {
        "type": "prometheus",
        "uid": "${datasource}"
      },
      "description": "Number of currently executing (also called \"live\") threads",
      "fieldConfig": {
        "defaults": {
          "color": {
            "mode": "palette-classic"
          },
          "custom": {
            "axisBorderShow": false,
            "axisCenteredZero": false,
            "axisColorMode": "text",
            "axisLabel": "",
            "axisPlacement": "auto",
            "barAlignment": 0,
            "drawStyle": "line",
            "fillOpacity": 25,
            "gradientMode": "none",
            "hideFrom": {
              "legend": false,
              "tooltip": false,
              "viz": false
            },
            "insertNulls": false,
            "lineInterpolation": "linear",
            "lineWidth": 1,
            "pointSize": 5,
            "scaleDistribution": {
              "type": "linear"
            },
            "showPoints": "auto",
            "spanNulls": false,
            "stacking": {
              "group": "A",
              "mode": "none"
            },
            "thresholdsStyle": {
              "mode": "off"
            }
          },
          "mappings": [],
          "thresholds": {
            "mode": "absolute",
            "steps": [
              {
                "color": "green",
                "value": null
              },
              {
                "color": "red",
                "value": 80
              }
            ]
          },
          "unit": "none"
        },
        "overrides": []
      },
      "gridPos": {
        "h": 7,
        "w": 11,
        "x": 13,
        "y": 15
      },
      "id": 42,
      "options": {
        "legend": {
          "calcs": [],
          "displayMode": "list",
          "placement": "bottom",
          "showLegend": true
        },
        "tooltip": {
          "mode": "single",
          "sort": "none"
        }
      },
      "targets": [
        {
          "datasource": {
            "type": "prometheus",
            "uid": "${datasource}"
          },
          "editorMode": "code",
          "expr": "process_thread_count",
          "legendFormat": "{{instance}}",
          "range": true,
          "refId": "A"
        }
      ],
      "title": "Threads",
      "type": "timeseries"
    }
  ],
  "refresh": "",
  "schemaVersion": 38,
  "tags": ["Python"],
  "templating": {
    "list": [
      {
        "current": {
          "selected": false,
          "text": "Prometheus",
          "value": "prometheus"
        },
        "description": "Choose a Prometheus data source",
        "hide": 0,
        "includeAll": false,
        "label": "Data source",
        "multi": false,
        "name": "datasource",
        "options": [],
        "query": "prometheus",
        "queryValue": "",
        "refresh": 1,
        "regex": "",
        "skipUrlSync": false,
        "type": "datasource"
      },
      {
        "allValue": ".+",
        "current": {
          "selected": false,
          "text": "All",
          "value": "$__all"
        },
        "datasource": {
          "type": "prometheus",
          "uid": "${datasource}"
        },
        "definition": "label_values(http_server_request_duration_seconds_count, job)",
        "hide": 0,
        "includeAll": true,
        "label": "Job",
        "multi": true,
        "name": "job",
        "options": [],
        "query": {
          "query": "label_values(http_server_request_duration_seconds_count, job)",
          "refId": "PrometheusVariableQueryEditor-VariableQuery"
        },
        "refresh": 2,
        "regex": "",
        "skipUrlSync": false,
        "sort": 1,
        "tagValuesQuery": "",
        "tagsQuery": "",
        "type": "query",
        "useTags": false
      },
      {
        "allValue": ".+",
        "current": {
          "selected": false,
          "text": "All",
          "value": "$__all"
        },
        "datasource": {
          "type": "prometheus",
          "uid": "${datasource}"
        },
        "definition": "label_values(http_server_request_duration_seconds_count, instance)",
        "description": "The instance of the application, e.g. pod1",
        "hide": 0,
        "includeAll": true,
        "label": "Instance",
        "multi": true,
        "name": "instance",
        "options": [],
        "query": {
          "query": "label_values(http_server_request_duration_seconds_count, instance)",
          "refId": "PrometheusVariableQueryEditor-VariableQuery"
        },
        "refresh": 2,
        "regex": "",
        "skipUrlSync": false,
        "sort": 1,
        "tagValuesQuery": "",
        "tagsQuery": "",
        "type": "query",
        "useTags": false
      }
    ]
  },
  "time": {
    "from": "now-1h",
    "to": "now"
  },
  "timepicker": {
    "refresh_intervals": [
      "5s",
      "10s",
      "30s",
      "1m",
      "5m",
      "15m",
      "30m",
      "1h",
      "2h",
      "1d"
    ],
    "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
  },
  "timezone": "",
  "title": "python-Objability",
  "uid": "python-dashboard-metrics",
  "version": 1,
  "weekStart": ""
}


1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?