Интеграция с Prometheus и Grafana, настройка алертов, централизованное логирование (ELK Stack), метрики производительности.
Интеграция с Prometheus и Grafana, настройка алертов, централизованное логирование (ELK Stack), метрики производительности
Вы развёртываете Gitea для команды. Всё работает, но что будет через месяц? Через полгода? Как узнать о проблемах до того, как пользователи начнут жаловаться?
Мониторинг отвечает на вопросы:
Логирование помогает:
Эта тема — о построении полной системы observability для Gitea.
┌─────────────────────────────────────────────────────────────────────┐
│ Gitea Server │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ Application │ │ PostgreSQL │ │ Git Repositories │ │
│ │ Metrics │ │ Metrics │ │ I/O │ │
│ │ /metrics │ │ pg_stat_* │ │ disk usage │ │
│ └────────┬────────┘ └────────┬────────┘ └──────────┬──────────┘ │
│ │ │ │ │
└───────────┼────────────────────┼───────────────────────┼─────────────┘
│ │ │
↓ ↓ ↓
┌─────────────────────────────────────────────────────────────────────┐
│ Prometheus │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Сбор метрик каждые 15 секунд, хранение до 90 дней │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────────────┐
│ Grafana │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Дашборды: обзор, репозитории, пользователи, CI/CD │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
│
↓
┌─────────────────────────────────────────────────────────────────────┐
│ Alertmanager │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ Алерты в Telegram, Slack, Email, PagerDuty │ │
│ └──────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
[metrics]
ENABLED = true
; Интервал сбора метрик (секунды)
INTERVAL = 60
; Токен для доступа к /metrics (опционально)
; TOKEN = your_metrics_token
[log]
MODE = console, file
LEVEL = info
[log.file]
LEVEL = info
FILE_NAME = gitea.log
MAX_SIZE_SHIFT = 28
DAILY_ROTATE = true
MAX_DAYS = 30# Без аутентификации (если не настроен токен)
curl http://git.company.ru:3000/metrics
# С токеном
curl -H "Authorization: Bearer your_metrics_token" \
http://git.company.ru:3000/metricsПример вывода:
# HELP go_gitea_repo_count Number of repositories
# TYPE go_gitea_repo_count gauge
go_gitea_repo_count 142
# HELP go_gitea_user_count Number of users
# TYPE go_gitea_user_count gauge
go_gitea_user_count 47
# HELP go_gitea_action_count_total Total number of actions
# TYPE go_gitea_action_count_total counter
go_gitea_action_count_total{type="create"} 523
go_gitea_action_count_total{type="push"} 1847
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.48.0
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=90d'
- '--web.enable-lifecycle'
networks:
- monitoring-net
grafana:
image: grafana/grafana:10.2.0
container_name: grafana
restart: unless-stopped
ports:
- "3001:3000"
volumes:
- ./grafana-data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=secure_password_2026
- GF_INSTALL_PLUGINS=grafana-piechart-panel
depends_on:
- prometheus
networks:
- monitoring-net
alertmanager:
image: prom/alertmanager:v0.26.0
container_name: alertmanager
restart: unless-stopped
ports:
- "9093:9093"
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
- ./alertmanager-data:/alertmanager
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
- '--storage.path=/alertmanager'
networks:
- monitoring-net
node-exporter:
image: prom/node-exporter:v1.7.0
container_name: node-exporter
restart: unless-stopped
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--path.rootfs=/rootfs'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
networks:
- monitoring-net
networks:
monitoring-net:
driver: bridgeglobal:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
rule_files:
- "alerts.yml"
scrape_configs:
# Prometheus self-monitoring
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# Gitea metrics
- job_name: 'gitea'
static_configs:
- targets: ['gitea:3000']
metrics_path: '/metrics'
# Node exporter (системные метрики)
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
# PostgreSQL exporter (опционально)
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']groups:
- name: gitea-alerts
rules:
# Gitea недоступна
- alert: GiteaDown
expr: up{job="gitea"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Gitea server is down"
description: "Gitea instance {{ $labels.instance }} has been down for more than 1 minute."
# Высокая нагрузка CPU
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage detected"
description: "CPU usage is above 80% on {{ $labels.instance }}"
# Мало места на диске
- alert: LowDiskSpace
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 20
for: 10m
labels:
severity: warning
annotations:
summary: "Low disk space warning"
description: "Disk space is below 20% on {{ $labels.instance }}"
# Критически мало места
- alert: CriticalDiskSpace
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
for: 5m
labels:
severity: critical
annotations:
summary: "Critical disk space"
description: "Disk space is below 10% on {{ $labels.instance }}"
# Много ошибок 5xx
- alert: HighErrorRate
expr: rate(gitea_http_response_status_count{code=~"5.."}[5m]) > 0.1
for: 5m
labels:
severity: warning
annotations:
summary: "High HTTP 5xx error rate"
description: "Error rate is {{ $value }} errors per second"
# Долгое время ответа
- alert: SlowResponseTime
expr: histogram_quantile(0.95, rate(gitea_http_request_duration_seconds_bucket[5m])) > 2
for: 10m
labels:
severity: warning
annotations:
summary: "Slow response time"
description: "95th percentile response time is {{ $value }} seconds"http://your-server:3001http://prometheus:9090Готовые дашборды для Gitea:
Gitea Official Dashboard (ID: 16789)
Node Exporter Full (ID: 1860)
Импорт:
{
"dashboard": {
"title": "Gitea Overview",
"panels": [
{
"title": "Repository Count",
"type": "stat",
"targets": [
{
"expr": "go_gitea_repo_count"
}
]
},
{
"title": "User Count",
"type": "stat",
"targets": [
{
"expr": "go_gitea_user_count"
}
]
},
{
"title": "HTTP Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(gitea_http_request_duration_seconds_count[5m])"
}
]
},
{
"title": "Error Rate (5xx)",
"type": "graph",
"targets": [
{
"expr": "rate(gitea_http_response_status_count{code=~\"5..\"}[5m])"
}
]
}
]
}
}global:
resolve_timeout: 5m
# Telegram
telegram_api_url: "https://api.telegram.org"
# SMTP для email
smtp_smarthost: 'smtp.company.ru:587'
smtp_from: 'alertmanager@company.ru'
smtp_auth_username: 'alertmanager@company.ru'
smtp_auth_password: 'smtp_password'
route:
group_by: ['alertname', 'severity']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'default-receiver'
routes:
- match:
severity: critical
receiver: 'telegram-critical'
continue: true
- match:
severity: warning
receiver: 'email-warnings'
receivers:
- name: 'default-receiver'
webhook_configs:
- url: 'http://localhost:5001/webhook'
- name: 'telegram-critical'
telegram_configs:
- bot_token: 'YOUR_BOT_TOKEN'
chat_id: '-1001234567890'
message: |
🚨 *Critical Alert*
Alert: {{ .GroupLabels.alertname }}
Severity: {{ .GroupLabels.severity }}
Summary: {{ .CommonAnnotations.summary }}
Description: {{ .CommonAnnotations.description }}
Time: {{ .StartsAt.Format "2006-01-02 15:04:05" }}
- name: 'email-warnings'
email_configs:
- to: 'devops@company.ru'
subject: '[WARNING] {{ .GroupLabels.alertname }}'
body: |
{{ range .Alerts }}
Alert: {{ .Labels.alertname }}
Severity: {{ .Labels.severity }}
Summary: {{ .Annotations.summary }}
Description: {{ .Annotations.description }}
{{ end }}
inhibit_rules:
# Если critical, не отправлять warning для того же алерта
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['alertname', 'instance']┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Gitea │ → │ Filebeat │ → │ Logstash │
│ logs │ │ (агент) │ │ (обработка)│
└─────────────┘ └─────────────┘ └──────┬──────┘
│
↓
┌─────────────┐
│Elasticsearch│
│ (хранение) │
└──────┬──────┘
│
↓
┌─────────────┐
│ Kibana │
│ (визуализ.) │
└─────────────┘
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0
container_name: elasticsearch
restart: unless-stopped
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms2g -Xmx2g"
volumes:
- ./elasticsearch-data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
networks:
- elk-net
logstash:
image: docker.elastic.co/logstash/logstash:8.11.0
container_name: logstash
restart: unless-stopped
volumes:
- ./logstash/pipeline:/usr/share/logstash/pipeline
- ./logstash/config:/usr/share/logstash/config
ports:
- "5044:5044"
depends_on:
- elasticsearch
networks:
- elk-net
kibana:
image: docker.elastic.co/kibana/kibana:8.11.0
container_name: kibana
restart: unless-stopped
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
depends_on:
- elasticsearch
networks:
- elk-net
filebeat:
image: docker.elastic.co/beats/filebeat:8.11.0
container_name: filebeat
restart: unless-stopped
user: root
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
- /opt/gitea/logs:/var/log/gitea:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
depends_on:
- logstash
networks:
- elk-net
networks:
elk-net:
driver: bridgefilebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/gitea/*.log
fields:
service: gitea
fields_under_root: true
- type: docker
enabled: true
containers:
paths:
- /var/lib/docker/containers/*/*.log
processors:
- add_docker_metadata:
host: "unix:///var/run/docker.sock"
output.logstash:
hosts: ["logstash:5044"]
logging.level: info
logging.to_files: true
logging.files:
path: /var/log/filebeat
name: filebeat.log
keepfiles: 7
permissions: 0644input {
beats {
port => 5044
}
}
filter {
if [service] == "gitea" {
grok {
match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:level} %{GREEDYDATA:log_message}" }
}
date {
match => [ "timestamp", "yyyy-MM-dd HH:mm:ss" ]
target => "@timestamp"
}
if "audit" in [path] {
mutate {
add_field => { "log_type" => "audit" }
}
}
}
if [docker] {
mutate {
add_field => { "log_type" => "docker" }
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "gitea-logs-%{+YYYY.MM.dd}"
}
# Debug вывод
stdout { codec => rubydebug }
}
http://your-server:5601gitea-logs-*@timestampПримеры запросов в Kibana:
# Все логи уровня ERROR
level: ERROR
# Аудит логины
log_type: audit AND action: login
# Ошибки за последний час
@timestamp > now-1h AND level: ERROR
# Действия конкретного пользователя
user: admin
# Доступ к конкретному репозиторию
repo: backend-api
| Метрика | Описание | Порог алерта |
|---|---|---|
| Uptime | Доступность Gitea | < 99.5% |
| Response Time (p95) | 95-й перцентиль времени ответа | > 2 сек |
| Error Rate (5xx) | Процент ошибок 5xx | > 1% |
| Disk Usage | Использование диска | > 80% |
| Memory Usage | Использование памяти | > 90% |
| Active Users | Активные пользователи за час | Мониторинг тренда |
| Git Operations | Количество git-операций | Мониторинг тренда |
| Actions Queue | Очередь CI/CD задач | > 10 задач |
Gitea Health (основной)
Repository Metrics
CI/CD Dashboard
Security Audit
/metricsСледующий шаг: LDAP/SSO аутентификация и управление доступом
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.