Files
a301_server/pkg/metrics/metrics.go
tolelom 844a5b264b feat: 보안 수정 + Prometheus 메트릭 + 단위 테스트 추가
보안:
- Zip Bomb 방어 (io.LimitReader 100MB)
- Redis Del 에러 로깅 (auth, idempotency)
- 로그인 실패 로그에서 username 제거
- os.Remove 에러 로깅

모니터링:
- Prometheus 메트릭 미들웨어 + /metrics 엔드포인트
- http_requests_total, http_request_duration_seconds 등 4개 메트릭

테스트:
- download (11), chain (10), bossraid (20) = 41개 단위 테스트

기타:
- DB 모델 GORM 인덱스 태그 추가
- launcherHash 필드 + hashFileToHex() 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:37:42 +09:00

55 lines
1.6 KiB
Go

package metrics
import (
"io"
"net/http"
"net/http/httptest"
"github.com/gofiber/fiber/v2"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
HTTPRequestsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{Name: "http_requests_total", Help: "Total HTTP requests"},
[]string{"method", "path", "status"},
)
HTTPRequestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{Name: "http_request_duration_seconds", Help: "HTTP request duration"},
[]string{"method", "path"},
)
DBConnectionsActive = prometheus.NewGauge(
prometheus.GaugeOpts{Name: "db_connections_active", Help: "Active DB connections"},
)
RedisConnectionsActive = prometheus.NewGauge(
prometheus.GaugeOpts{Name: "redis_connections_active", Help: "Active Redis connections"},
)
)
func init() {
prometheus.MustRegister(HTTPRequestsTotal, HTTPRequestDuration, DBConnectionsActive, RedisConnectionsActive)
}
// Handler returns a Fiber handler that serves the Prometheus metrics endpoint.
// It wraps promhttp.Handler() without requiring the gofiber/adaptor package.
func Handler(c *fiber.Ctx) error {
handler := promhttp.Handler()
req, err := http.NewRequest(http.MethodGet, "/metrics", nil)
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
result := rec.Result()
defer result.Body.Close()
c.Set("Content-Type", result.Header.Get("Content-Type"))
c.Status(result.StatusCode)
body, err := io.ReadAll(result.Body)
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.Send(body)
}