1. はじめに
OpenTelemetryの学習にあたり、公式デモを、ようやく動かせるようになったので、それを忘れないうちに、Python(Flask/Locust)特化のシンプルな最小構成環境を作ってみました。
手作業を排除し、EC2上にインフラ構築から自動監視までをTerraformで自動作成します。
今回は 【Vol.1】環境構築編 として、まずは動かすことに特化しています。
自分自身の学習記録の備忘録としての意味合いもあります。
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上にインフラ環境を自動構築します。
アプリケーション & 自動監視環境 ( ./ENV_1011/ )
main.tf を実行し、EC2インスタンス起動後に、環境構築/python実行で必要なファイルを格納しています。
5. システム構成
今回は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)をプル
🔄 各コンポーネントの役割
6. メトリクス
ダッシュボードで可視化したメトリクスは以下の通りです。
Locustの負荷変動に応じて、これらの値も変動します。
具体的なコードについては、末尾の 【付録:環境構築用コード】 にある「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がバックグラウンドで以下の処理を全自動で実行します。
-
GitのSparse Checkout(部分チェックアウト) を使い、リポジトリから必要なディレクトリ(
ENV_1011)のみダウンロード。 - Docker / Docker Compose のインストールと起動。
- 公式スクリプト(
run-lgtm.sh)によるLGTMスタックコンテナ起動。 - Python 3.11環境の構築と、必要ライブラリ(Flask, OpenTelemetry SDK, Locustなど)のインストール。
- 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 からダッシュボード選択を行います。
メニュー選択
表示期間を「⏱ Last 5 minutes」に切り替えて、10分ほど待つと、以下のようなデータが見られるようになります。
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": ""
}






