From 126134c68131ee2dc3969cd20f83f29a33f493d3 Mon Sep 17 00:00:00 2001 From: minibr Date: Fri, 15 May 2026 20:51:48 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20Prometheus=20+=20Grafana=20?= =?UTF-8?q?=EB=AA=A8=EB=8B=88=ED=84=B0=EB=A7=81=20=EA=B5=AC=EC=84=B1=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-cd.yml | 25 ++++++++++++++ .gitignore | 6 ++++ build.gradle | 1 + docker/docker-compose.yml | 58 ++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) diff --git a/.github/workflows/backend-cd.yml b/.github/workflows/backend-cd.yml index e8ceedae..197d25af 100644 --- a/.github/workflows/backend-cd.yml +++ b/.github/workflows/backend-cd.yml @@ -78,6 +78,31 @@ jobs: - name: ✨ Checkout repository uses: actions/checkout@v5 + - name: πŸ—‚οΈ Make monitoring config + run: | + # Prometheus μ„€μ • + mkdir -p ./docker + echo "$PROMETHEUS_YML" > ./docker/prometheus.yml + + # Grafana provisioning μ„€μ • + mkdir -p ./docker/grafana/provisioning/datasources + mkdir -p ./docker/grafana/provisioning/dashboards + mkdir -p ./docker/grafana/dashboards + + echo "$GRAFANA_DATASOURCE_YML" > ./docker/grafana/provisioning/datasources/prometheus.yml + echo "$GRAFANA_DASHBOARD_PROVIDER_YML" > ./docker/grafana/provisioning/dashboards/dashboards.yml + echo "$GRAFANA_DASHBOARD_JSON" > ./docker/grafana/dashboards/http-overview.json + + # Grafana ν™˜κ²½λ³€μˆ˜ + echo "$DOCKER_ENV" > ./docker/.env + env: + PROMETHEUS_YML: ${{ secrets.PROMETHEUS_YML }} + GRAFANA_DATASOURCE_YML: ${{ secrets.GRAFANA_DATASOURCE_YML }} + GRAFANA_DASHBOARD_PROVIDER_YML: ${{ secrets.GRAFANA_DASHBOARD_PROVIDER_YML }} + GRAFANA_DASHBOARD_JSON: ${{ secrets.GRAFANA_DASHBOARD_JSON }} + DOCKER_ENV: ${{ secrets.DOCKER_ENV }} + shell: bash + - name: ✨ 배포 슀크립트 μ‹€ν–‰ run: | chmod +x deploy.sh diff --git a/.gitignore b/.gitignore index a0cb7de3..2bac80c7 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,9 @@ out/ ### Spring *.yml .editorconfig + +### Environment +.env +docker/.env +docker/prometheus.yml +docker/grafana/ diff --git a/build.gradle b/build.gradle index bf335544..25d76912 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-actuator' + runtimeOnly 'io.micrometer:micrometer-registry-prometheus' //Test testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index adca8632..6ecc9183 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -52,6 +52,64 @@ services: max-size: "10m" max-file: "3" + prometheus: + image: prom/prometheus:v2.53.0 + container_name: prometheus + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro + - prometheus_data:/prometheus + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--storage.tsdb.retention.time=3d' + - '--web.enable-lifecycle' + ports: + - '9090:9090' + restart: unless-stopped + networks: + - app-network + deploy: + resources: + limits: + memory: 256M + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + grafana: + image: grafana/grafana:11.1.0 + container_name: grafana + volumes: + - grafana_data:/var/lib/grafana + - ./grafana/provisioning:/etc/grafana/provisioning:ro + - ./grafana/dashboards:/var/lib/grafana/dashboards:ro + environment: + - GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER:-admin} + - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} + - GF_USERS_ALLOW_SIGN_UP=false + ports: + - '3001:3000' + restart: unless-stopped + networks: + - app-network + deploy: + resources: + limits: + memory: 256M + depends_on: + - prometheus + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + +volumes: + prometheus_data: + grafana_data: + networks: app-network: driver: bridge From 8cd86121421358b5d5458c10e9e97f5db16c44a6 Mon Sep 17 00:00:00 2001 From: minibr Date: Fri, 15 May 2026 21:16:20 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20Grafana=20=EB=8C=80=EC=8B=9C?= =?UTF-8?q?=EB=B3=B4=EB=93=9C=20=EB=B0=8F=20Prometheus=20=EB=AA=A8?= =?UTF-8?q?=EB=8B=88=ED=84=B0=EB=A7=81=20=EC=84=A4=EC=A0=95=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-cd.yml | 25 +- .gitignore | 8 +- docker/grafana/dashboards/http-overview.json | 457 ++++++++++++++++++ .../provisioning/dashboards/dashboards.yml | 11 + .../provisioning/datasources/prometheus.yml | 9 + docker/prometheus.yml | 13 + 6 files changed, 495 insertions(+), 28 deletions(-) create mode 100644 docker/grafana/dashboards/http-overview.json create mode 100644 docker/grafana/provisioning/dashboards/dashboards.yml create mode 100644 docker/grafana/provisioning/datasources/prometheus.yml create mode 100644 docker/prometheus.yml diff --git a/.github/workflows/backend-cd.yml b/.github/workflows/backend-cd.yml index 197d25af..e8036729 100644 --- a/.github/workflows/backend-cd.yml +++ b/.github/workflows/backend-cd.yml @@ -78,29 +78,10 @@ jobs: - name: ✨ Checkout repository uses: actions/checkout@v5 - - name: πŸ—‚οΈ Make monitoring config + - name: πŸ—‚οΈ Grafana ν™˜κ²½λ³€μˆ˜ μ„€μ • run: | - # Prometheus μ„€μ • - mkdir -p ./docker - echo "$PROMETHEUS_YML" > ./docker/prometheus.yml - - # Grafana provisioning μ„€μ • - mkdir -p ./docker/grafana/provisioning/datasources - mkdir -p ./docker/grafana/provisioning/dashboards - mkdir -p ./docker/grafana/dashboards - - echo "$GRAFANA_DATASOURCE_YML" > ./docker/grafana/provisioning/datasources/prometheus.yml - echo "$GRAFANA_DASHBOARD_PROVIDER_YML" > ./docker/grafana/provisioning/dashboards/dashboards.yml - echo "$GRAFANA_DASHBOARD_JSON" > ./docker/grafana/dashboards/http-overview.json - - # Grafana ν™˜κ²½λ³€μˆ˜ - echo "$DOCKER_ENV" > ./docker/.env - env: - PROMETHEUS_YML: ${{ secrets.PROMETHEUS_YML }} - GRAFANA_DATASOURCE_YML: ${{ secrets.GRAFANA_DATASOURCE_YML }} - GRAFANA_DASHBOARD_PROVIDER_YML: ${{ secrets.GRAFANA_DASHBOARD_PROVIDER_YML }} - GRAFANA_DASHBOARD_JSON: ${{ secrets.GRAFANA_DASHBOARD_JSON }} - DOCKER_ENV: ${{ secrets.DOCKER_ENV }} + echo "GRAFANA_ADMIN_USER=admin" > ./docker/.env + echo "GRAFANA_ADMIN_PASSWORD=${{ secrets.GRAFANA_ADMIN_PASSWORD }}" >> ./docker/.env shell: bash - name: ✨ 배포 슀크립트 μ‹€ν–‰ diff --git a/.gitignore b/.gitignore index 2bac80c7..aac9bcd6 100644 --- a/.gitignore +++ b/.gitignore @@ -35,10 +35,6 @@ out/ ### Spring *.yml +!docker/prometheus.yml +!docker/grafana/**/*.yml .editorconfig - -### Environment -.env -docker/.env -docker/prometheus.yml -docker/grafana/ diff --git a/docker/grafana/dashboards/http-overview.json b/docker/grafana/dashboards/http-overview.json new file mode 100644 index 00000000..82c53d57 --- /dev/null +++ b/docker/grafana/dashboards/http-overview.json @@ -0,0 +1,457 @@ +{ + "annotations": { + "list": [] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "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": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m]))", + "legendFormat": "Total RPS", + "refId": "A" + } + ], + "title": "HTTP Request Rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "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": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\", status=~\"5..\"}[1m])) / sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) * 100", + "legendFormat": "5xx Error Rate", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\", status=~\"4..\"}[1m])) / sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) * 100", + "legendFormat": "4xx Error Rate", + "refId": "B" + } + ], + "title": "HTTP Error Rate (%)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "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": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "histogram_quantile(0.50, sum(rate(http_server_requests_seconds_bucket{application=\"linkiving-core\"}[1m])) by (le))", + "legendFormat": "p50", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{application=\"linkiving-core\"}[1m])) by (le))", + "legendFormat": "p95", + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{application=\"linkiving-core\"}[1m])) by (le))", + "legendFormat": "p99", + "refId": "C" + } + ], + "title": "HTTP Response Time (Percentiles)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "bars", + "fillOpacity": 100, + "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": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "reqps" + }, + "overrides": [ + { + "matcher": { + "id": "byRegexp", + "options": "2.." + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "4.." + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "yellow", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byRegexp", + "options": "5.." + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "red", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) by (status)", + "legendFormat": "{{status}}", + "refId": "A" + } + ], + "title": "HTTP Requests by Status Code", + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 39, + "tags": ["http", "spring-boot"], + "templating": { + "list": [] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "Asia/Seoul", + "title": "Linkiving HTTP Overview", + "uid": "linkiving-http-overview", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/docker/grafana/provisioning/dashboards/dashboards.yml b/docker/grafana/provisioning/dashboards/dashboards.yml new file mode 100644 index 00000000..391325b2 --- /dev/null +++ b/docker/grafana/provisioning/dashboards/dashboards.yml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: + - name: 'default' + orgId: 1 + folder: '' + type: file + disableDeletion: false + editable: true + options: + path: /var/lib/grafana/dashboards \ No newline at end of file diff --git a/docker/grafana/provisioning/datasources/prometheus.yml b/docker/grafana/provisioning/datasources/prometheus.yml new file mode 100644 index 00000000..d1792ffc --- /dev/null +++ b/docker/grafana/provisioning/datasources/prometheus.yml @@ -0,0 +1,9 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: false \ No newline at end of file diff --git a/docker/prometheus.yml b/docker/prometheus.yml new file mode 100644 index 00000000..86d2b091 --- /dev/null +++ b/docker/prometheus.yml @@ -0,0 +1,13 @@ +global: + scrape_interval: 30s + evaluation_interval: 30s + +scrape_configs: + - job_name: 'linkiving-core' + metrics_path: '/actuator/prometheus' + static_configs: + - targets: + - 'blue:8080' + - 'green:8080' + labels: + application: 'linkiving-core' \ No newline at end of file From bd999cc9d89c3b669bea64b17fa6ded6d85a897d Mon Sep 17 00:00:00 2001 From: minibr Date: Fri, 15 May 2026 21:48:52 +0900 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20Grafana=20datasource=20uid=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/grafana/dashboards/http-overview.json | 22 +++++++++---------- .../provisioning/datasources/prometheus.yml | 1 + 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docker/grafana/dashboards/http-overview.json b/docker/grafana/dashboards/http-overview.json index 82c53d57..96dbf664 100644 --- a/docker/grafana/dashboards/http-overview.json +++ b/docker/grafana/dashboards/http-overview.json @@ -11,7 +11,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "fieldConfig": { "defaults": { @@ -87,7 +87,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m]))", "legendFormat": "Total RPS", @@ -100,7 +100,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "fieldConfig": { "defaults": { @@ -176,7 +176,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\", status=~\"5..\"}[1m])) / sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) * 100", "legendFormat": "5xx Error Rate", @@ -185,7 +185,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\", status=~\"4..\"}[1m])) / sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) * 100", "legendFormat": "4xx Error Rate", @@ -198,7 +198,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "fieldConfig": { "defaults": { @@ -274,7 +274,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "expr": "histogram_quantile(0.50, sum(rate(http_server_requests_seconds_bucket{application=\"linkiving-core\"}[1m])) by (le))", "legendFormat": "p50", @@ -283,7 +283,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "expr": "histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket{application=\"linkiving-core\"}[1m])) by (le))", "legendFormat": "p95", @@ -292,7 +292,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "expr": "histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{application=\"linkiving-core\"}[1m])) by (le))", "legendFormat": "p99", @@ -305,7 +305,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "fieldConfig": { "defaults": { @@ -427,7 +427,7 @@ { "datasource": { "type": "prometheus", - "uid": "PBFA97CFB590B2093" + "uid": "prometheus" }, "expr": "sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) by (status)", "legendFormat": "{{status}}", diff --git a/docker/grafana/provisioning/datasources/prometheus.yml b/docker/grafana/provisioning/datasources/prometheus.yml index d1792ffc..12914e77 100644 --- a/docker/grafana/provisioning/datasources/prometheus.yml +++ b/docker/grafana/provisioning/datasources/prometheus.yml @@ -5,5 +5,6 @@ datasources: type: prometheus access: proxy url: http://prometheus:9090 + uid: prometheus isDefault: true editable: false \ No newline at end of file From 620814b2b0738e2591aad70d51b3691bae6ef0d1 Mon Sep 17 00:00:00 2001 From: minibr Date: Thu, 21 May 2026 14:54:16 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20actuator=20=EC=97=94=EB=93=9C?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20Security=20=ED=97=88=EC=9A=A9=20?= =?UTF-8?q?=EB=B0=8F=20=EB=AA=A8=EB=8B=88=ED=84=B0=EB=A7=81=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EC=9E=90=EB=8F=99=20=EC=8B=A4=ED=96=89=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy.sh | 13 +++++++++++++ .../security/auth/config/SecurityConstants.java | 3 +++ 2 files changed, 16 insertions(+) diff --git a/deploy.sh b/deploy.sh index 6e69a6d0..b4b62453 100644 --- a/deploy.sh +++ b/deploy.sh @@ -32,6 +32,19 @@ if ! ${COMPOSE} pull; then fi echo "βœ… μƒˆλ‘œμš΄ 이미지가 μ„±κ³΅μ μœΌλ‘œ pullλ˜μ—ˆμŠ΅λ‹ˆλ‹€." +# Prometheus & Grafana μ‹€ν–‰ (이미 μ‹€ν–‰ 쀑이면 μŠ€ν‚΅) +echo "λͺ¨λ‹ˆν„°λ§ μ„œλΉ„μŠ€ 확인 쀑..." +PROMETHEUS_RUNNING=$(sudo docker ps --filter "name=prometheus" --filter "status=running" -q) +GRAFANA_RUNNING=$(sudo docker ps --filter "name=grafana" --filter "status=running" -q) + +if [ -z "$PROMETHEUS_RUNNING" ] || [ -z "$GRAFANA_RUNNING" ]; then + echo "λͺ¨λ‹ˆν„°λ§ μ„œλΉ„μŠ€ μ‹œμž‘ 쀑..." + ${COMPOSE} up -d prometheus grafana + echo "βœ… Prometheus & Grafanaκ°€ μ‹œμž‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€." +else + echo "βœ… λͺ¨λ‹ˆν„°λ§ μ„œλΉ„μŠ€κ°€ 이미 μ‹€ν–‰ μ€‘μž…λ‹ˆλ‹€." +fi + echo "μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 이미지 정리 쀑..." sudo docker image prune -f diff --git a/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java b/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java index 2df653a2..8610f4b2 100644 --- a/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java +++ b/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java @@ -5,6 +5,9 @@ public abstract class SecurityConstants { /* swagger */ "/v3/api-docs/**", "/swagger-ui/**", "/swagger-resources", "/swagger-resources/**", + /* actuator */ + "/actuator/prometheus", "/actuator/health", + /* health check */ "/health-check", From eeaa5390b950b545fb9b870dbd316f460a46a38e Mon Sep 17 00:00:00 2001 From: minibr Date: Thu, 21 May 2026 15:32:49 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=EC=97=94=EB=93=9C=ED=8F=AC?= =?UTF-8?q?=EC=9D=B8=ED=8A=B8=EB=B3=84=20=EC=9D=91=EB=8B=B5=EC=8B=9C?= =?UTF-8?q?=EA=B0=84/=EC=9A=94=EC=B2=AD=EC=88=98=20=EB=8C=80=EC=8B=9C?= =?UTF-8?q?=EB=B3=B4=EB=93=9C=20=ED=8C=A8=EB=84=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/grafana/dashboards/http-overview.json | 178 +++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/docker/grafana/dashboards/http-overview.json b/docker/grafana/dashboards/http-overview.json index 96dbf664..6fdedbce 100644 --- a/docker/grafana/dashboards/http-overview.json +++ b/docker/grafana/dashboards/http-overview.json @@ -436,6 +436,184 @@ ], "title": "HTTP Requests by Status Code", "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "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": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "topk(10, avg(rate(http_server_requests_seconds_sum{application=\"linkiving-core\"}[1m])) by (uri) / avg(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) by (uri))", + "legendFormat": "{{uri}}", + "refId": "A" + } + ], + "title": "Top 10 Slowest Endpoints (Avg Response Time)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "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": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "topk(10, sum(rate(http_server_requests_seconds_count{application=\"linkiving-core\"}[1m])) by (uri))", + "legendFormat": "{{uri}}", + "refId": "A" + } + ], + "title": "Top 10 Most Requested Endpoints", + "type": "timeseries" } ], "refresh": "30s", From 74950cf8cbc05881a6752fcc99505ff3353b1e1a Mon Sep 17 00:00:00 2001 From: minibr Date: Sun, 31 May 2026 14:29:24 +0900 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=EB=AA=A8=EB=8B=88=ED=84=B0=EB=A7=81?= =?UTF-8?q?=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=ED=95=AD=EC=83=81=20up=20-d?= =?UTF-8?q?=20=EC=8B=A4=ED=96=89=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy.sh | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/deploy.sh b/deploy.sh index b4b62453..12287fa5 100644 --- a/deploy.sh +++ b/deploy.sh @@ -32,18 +32,10 @@ if ! ${COMPOSE} pull; then fi echo "βœ… μƒˆλ‘œμš΄ 이미지가 μ„±κ³΅μ μœΌλ‘œ pullλ˜μ—ˆμŠ΅λ‹ˆλ‹€." -# Prometheus & Grafana μ‹€ν–‰ (이미 μ‹€ν–‰ 쀑이면 μŠ€ν‚΅) -echo "λͺ¨λ‹ˆν„°λ§ μ„œλΉ„μŠ€ 확인 쀑..." -PROMETHEUS_RUNNING=$(sudo docker ps --filter "name=prometheus" --filter "status=running" -q) -GRAFANA_RUNNING=$(sudo docker ps --filter "name=grafana" --filter "status=running" -q) - -if [ -z "$PROMETHEUS_RUNNING" ] || [ -z "$GRAFANA_RUNNING" ]; then - echo "λͺ¨λ‹ˆν„°λ§ μ„œλΉ„μŠ€ μ‹œμž‘ 쀑..." - ${COMPOSE} up -d prometheus grafana - echo "βœ… Prometheus & Grafanaκ°€ μ‹œμž‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€." -else - echo "βœ… λͺ¨λ‹ˆν„°λ§ μ„œλΉ„μŠ€κ°€ 이미 μ‹€ν–‰ μ€‘μž…λ‹ˆλ‹€." -fi +# Prometheus & Grafana μ‹€ν–‰ (μ„€μ • λ³€κ²½ μ‹œ μžλ™ 반영) +echo "λͺ¨λ‹ˆν„°λ§ μ„œλΉ„μŠ€ μ‹œμž‘ 쀑..." +${COMPOSE} up -d prometheus grafana +echo "βœ… Prometheus & Grafanaκ°€ μ‹œμž‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€." echo "μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 이미지 정리 쀑..." sudo docker image prune -f From 5ed578c068b7f860ff85aa596893027e43c80e5e Mon Sep 17 00:00:00 2001 From: minibr Date: Sun, 21 Jun 2026 20:51:26 +0900 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20=EB=AA=A8=EB=8B=88=ED=84=B0=EB=A7=81?= =?UTF-8?q?=20=EB=B3=B4=EC=95=88=20=EC=84=A4=EC=A0=95=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/docker-compose.yml | 4 ---- .../linkiving/security/auth/config/SecurityConstants.java | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 6ecc9183..0a6c4e82 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,6 +1,4 @@ # docker-compose.yml -version: '3.8' - services: blue: image: linkivingsofa/core:latest @@ -63,8 +61,6 @@ services: - '--storage.tsdb.path=/prometheus' - '--storage.tsdb.retention.time=3d' - '--web.enable-lifecycle' - ports: - - '9090:9090' restart: unless-stopped networks: - app-network diff --git a/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java b/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java index 8610f4b2..34f0a59d 100644 --- a/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java +++ b/src/main/java/com/sofa/linkiving/security/auth/config/SecurityConstants.java @@ -6,7 +6,8 @@ public abstract class SecurityConstants { "/v3/api-docs/**", "/swagger-ui/**", "/swagger-resources", "/swagger-resources/**", /* actuator */ - "/actuator/prometheus", "/actuator/health", + "/actuator/health", + "/actuator/prometheus", /* health check */ "/health-check",