Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# 로컬 모니터링 스택 실행 전, 이 파일을 .env로 복사하고 실제 값을 채우세요.
# .env는 .gitignore에 포함되어 있어 커밋되지 않습니다.

SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXXXXXXX/XXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX
1 change: 0 additions & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
*.java @funnysunny08 @RinRinPARK @YuSuhwa-ve
2 changes: 1 addition & 1 deletion .github/workflows/dev-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: make application.properties 파일 생성
run: |
## create application.yml
mkdir ./src/main/resources
mkdir -p ./src/main/resources
cd ./src/main/resources

# application.yml 파일 생성
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dev-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: make application.properties 파일 생성
run: |
## create application.yml
mkdir ./src/main/resources
mkdir -p ./src/main/resources
cd ./src/main/resources

# application.yml 파일 생성
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/prod-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: make application.properties 파일 생성
run: |
## create application.yml
mkdir ./src/main/resources
mkdir -p ./src/main/resources
cd ./src/main/resources

# application.yml 파일 생성
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/prod-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: make application.properties 파일 생성
run: |
## create application.yml
mkdir ./src/main/resources
mkdir -p ./src/main/resources
cd ./src/main/resources

# application.yml 파일 생성
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ application.yaml

### DS_Store
.DS_Store
logs/
test_write.tmp
.env
26 changes: 26 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# --- Build stage ---
FROM gradle:8.2.1-jdk11 AS build
WORKDIR /app

COPY build.gradle settings.gradle ./
COPY gradle ./gradle
COPY gradlew ./

COPY src ./src

# 로컬/모니터링 검증용 application.yml은 build context 루트에 두고 복사한다.
# (CI/CD에서는 GitHub Secret으로 별도 생성 — 이 Dockerfile은 로컬 검증 전용)
COPY application.yml ./application.yml

RUN ./gradlew bootJar -x test --no-daemon

# --- Run stage ---
FROM eclipse-temurin:11-jre
WORKDIR /app

COPY --from=build /app/build/libs/*.jar app.jar
COPY --from=build /app/application.yml application.yml

EXPOSE 8080

ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul", "-jar", "app.jar", "--spring.config.location=file:./application.yml"]
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ dependencies {
// Health Check
implementation 'org.springframework.boot:spring-boot-starter-actuator'

// Monitoring - Prometheus
implementation 'io.micrometer:micrometer-registry-prometheus:1.9.14'

// JPA & Database
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.27'
Expand Down
115 changes: 115 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
version: "3.8"

services:
runnect-app:
build:
context: .
dockerfile: Dockerfile
container_name: runnect-app
ports:
- "8080:8080"
depends_on:
- postgres
- redis
volumes:
- ./logs:/app/logs
networks:
- runnect-net

postgres:
image: postgres:15
container_name: runnect-postgres
environment:
POSTGRES_DB: runnect
POSTGRES_USER: runnect
POSTGRES_PASSWORD: runnect_local_password
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- runnect-net

redis:
image: redis:7
container_name: runnect-redis
ports:
- "6379:6379"
networks:
- runnect-net

elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4
container_name: runnect-elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- "9200:9200"
networks:
- runnect-net

logstash:
image: docker.elastic.co/logstash/logstash:8.13.4
container_name: runnect-logstash
depends_on:
- elasticsearch
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
- ./logs:/usr/share/logstash/logs
- logstash_data:/usr/share/logstash/data
ports:
- "5044:5044"
networks:
- runnect-net

kibana:
image: docker.elastic.co/kibana/kibana:8.13.4
container_name: runnect-kibana
depends_on:
- elasticsearch
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
networks:
- runnect-net

prometheus:
image: prom/prometheus:latest
container_name: runnect-prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
depends_on:
- runnect-app
networks:
- runnect-net

grafana:
image: grafana/grafana:latest
container_name: runnect-grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- SLACK_WEBHOOK_URL=${SLACK_WEBHOOK_URL}
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
- runnect-net

networks:
runnect-net:
driver: bridge

volumes:
postgres_data:
grafana_data:
logstash_data:
11 changes: 11 additions & 0 deletions grafana/provisioning/alerting/contact-points.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: 1

contactPoints:
- orgId: 1
name: slack-alert
receivers:
- uid: slack-alert-receiver
type: slack
settings:
url: $__env{SLACK_WEBHOOK_URL}
username: "Grafana"
11 changes: 11 additions & 0 deletions grafana/provisioning/alerting/contact-points.yml.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: 1

contactPoints:
- orgId: 1
name: slack-alert
receivers:
- uid: slack-alert-receiver
type: slack
settings:
url: "__SLACK_WEBHOOK_URL__"
username: "Grafana"
9 changes: 9 additions & 0 deletions grafana/provisioning/alerting/notification-policies.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: 1

policies:
- orgId: 1
receiver: slack-alert
group_by: ["alertname"]
group_wait: 10s
group_interval: 1m
repeat_interval: 10m
48 changes: 48 additions & 0 deletions grafana/provisioning/alerting/rules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
apiVersion: 1

groups:
- orgId: 1
name: runnect-alerts
folder: Runnect Alerts
interval: 30s
rules:
- uid: runnect-server-down
title: "Runnect Server Down"
condition: C
for: 30s
noDataState: Alerting
execErrState: Alerting
data:
- refId: A
datasourceUid: prometheus-ds
relativeTimeRange:
from: 120
to: 0
model:
expr: 'up{job="runnect-server"}'
instant: true
refId: A
- refId: C
datasourceUid: "-100"
relativeTimeRange:
from: 120
to: 0
model:
type: threshold
refId: C
expression: A
conditions:
- evaluator:
type: lt
params: [1]
operator:
type: and
query:
params: ["A"]
reducer:
type: last
params: []
annotations:
summary: "Runnect 서버가 응답하지 않고 있습니다 (up == 0)"
labels:
severity: critical
12 changes: 12 additions & 0 deletions grafana/provisioning/dashboards/dashboard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: 1

providers:
- name: "Runnect Dashboards"
orgId: 1
folder: ""
type: file
disableDeletion: false
updateIntervalSeconds: 30
options:
path: /etc/grafana/provisioning/dashboards/json
foldersFromFilesStructure: true
56 changes: 56 additions & 0 deletions grafana/provisioning/dashboards/json/runnect-overview.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"title": "Runnect Server Overview",
"timezone": "browser",
"schemaVersion": 39,
"refresh": "10s",
"panels": [
{
"id": 1,
"title": "JVM Heap Used (bytes)",
"type": "timeseries",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
"targets": [
{
"expr": "sum(jvm_memory_used_bytes{area=\"heap\", application=\"runnect-server\"})",
"legendFormat": "heap used"
}
]
},
{
"id": 2,
"title": "CPU Usage",
"type": "timeseries",
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 },
"targets": [
{
"expr": "process_cpu_usage{application=\"runnect-server\"}",
"legendFormat": "cpu usage"
}
]
},
{
"id": 3,
"title": "HTTP Requests per Second",
"type": "timeseries",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 },
"targets": [
{
"expr": "sum(rate(http_server_requests_seconds_count{application=\"runnect-server\"}[1m])) by (status)",
"legendFormat": "status {{status}}"
}
]
},
{
"id": 4,
"title": "Server Up",
"type": "stat",
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 },
"targets": [
{
"expr": "up{job=\"runnect-server\"}",
"legendFormat": "up"
}
]
}
]
}
10 changes: 10 additions & 0 deletions grafana/provisioning/datasources/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: 1

datasources:
- name: Prometheus
uid: prometheus-ds
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: true
32 changes: 32 additions & 0 deletions logstash.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
input {
file {
path => "/usr/share/logstash/logs/runnect-server.log"
start_position => "beginning"
codec => multiline {
pattern => "^%{TIMESTAMP_ISO8601}"
negate => true
what => "previous"
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

filter {
grok {
match => {
"message" => "%{TIMESTAMP_ISO8601:log_timestamp} \[%{DATA:traceId}\] %{LOGLEVEL:level}%{SPACE}\[%{DATA:thread}\] %{DATA:logger} - %{GREEDYDATA:log_message}"
}
}

date {
match => ["log_timestamp", "yyyy-MM-dd HH:mm:ss.SSS"]
timezone => "Asia/Seoul"
target => "@timestamp"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
}

output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "runnect-logs-%{+yyyy.MM.dd}"
}
}
Loading
Loading