feat: add observability improvements (metrics, audit log, structured logging)
All checks were successful
Check / check (pull_request) Successful in 1m45s
All checks were successful
Check / check (pull_request) Successful in 1m45s
- Add Prometheus metrics package (internal/metrics) with deployment, container health, webhook, HTTP request, and audit counters/histograms - Add audit_log SQLite table via migration 007 - Add AuditEntry model with CRUD operations and query methods - Add audit service (internal/service/audit) for recording user actions - Instrument deploy service with deployment duration, count, and in-flight metrics; container health gauge updates on deploy completion - Instrument webhook service with event counters by app/type/matched - Instrument HTTP middleware with request count, duration, and response size metrics; also log response bytes in structured request logs - Add audit logging to all key handler operations: login/logout, app CRUD, deploy, cancel, rollback, restart/stop/start, webhook receipt, and initial setup - Add GET /api/audit endpoint for querying recent audit entries - Make /metrics endpoint always available (optionally auth-protected) - Add comprehensive tests for metrics, audit model, and audit service - Update existing test infrastructure with metrics and audit dependencies - Update README with Observability section documenting all metrics, audit log, and structured logging
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/fx"
|
||||
@@ -24,8 +25,10 @@ import (
|
||||
"sneak.berlin/go/upaas/internal/handlers"
|
||||
"sneak.berlin/go/upaas/internal/healthcheck"
|
||||
"sneak.berlin/go/upaas/internal/logger"
|
||||
"sneak.berlin/go/upaas/internal/metrics"
|
||||
"sneak.berlin/go/upaas/internal/middleware"
|
||||
"sneak.berlin/go/upaas/internal/service/app"
|
||||
"sneak.berlin/go/upaas/internal/service/audit"
|
||||
"sneak.berlin/go/upaas/internal/service/auth"
|
||||
"sneak.berlin/go/upaas/internal/service/deploy"
|
||||
"sneak.berlin/go/upaas/internal/service/notify"
|
||||
@@ -92,7 +95,8 @@ func createAppServices(
|
||||
logInstance *logger.Logger,
|
||||
dbInstance *database.Database,
|
||||
cfg *config.Config,
|
||||
) (*auth.Service, *app.Service, *deploy.Service, *webhook.Service, *docker.Client) {
|
||||
metricsInstance *metrics.Metrics,
|
||||
) (*auth.Service, *app.Service, *deploy.Service, *webhook.Service, *docker.Client, *audit.Service) {
|
||||
t.Helper()
|
||||
|
||||
authSvc, authErr := auth.New(fx.Lifecycle(nil), auth.ServiceParams{
|
||||
@@ -125,6 +129,7 @@ func createAppServices(
|
||||
Database: dbInstance,
|
||||
Docker: dockerClient,
|
||||
Notify: notifySvc,
|
||||
Metrics: metricsInstance,
|
||||
})
|
||||
require.NoError(t, deployErr)
|
||||
|
||||
@@ -132,10 +137,18 @@ func createAppServices(
|
||||
Logger: logInstance,
|
||||
Database: dbInstance,
|
||||
Deploy: deploySvc,
|
||||
Metrics: metricsInstance,
|
||||
})
|
||||
require.NoError(t, webhookErr)
|
||||
|
||||
return authSvc, appSvc, deploySvc, webhookSvc, dockerClient
|
||||
auditSvc, auditErr := audit.New(fx.Lifecycle(nil), audit.ServiceParams{
|
||||
Logger: logInstance,
|
||||
Database: dbInstance,
|
||||
Metrics: metricsInstance,
|
||||
})
|
||||
require.NoError(t, auditErr)
|
||||
|
||||
return authSvc, appSvc, deploySvc, webhookSvc, dockerClient, auditSvc
|
||||
}
|
||||
|
||||
func setupTestHandlers(t *testing.T) *testContext {
|
||||
@@ -145,11 +158,14 @@ func setupTestHandlers(t *testing.T) *testContext {
|
||||
|
||||
globalInstance, logInstance, dbInstance, hcInstance := createCoreServices(t, cfg)
|
||||
|
||||
authSvc, appSvc, deploySvc, webhookSvc, dockerClient := createAppServices(
|
||||
metricsInstance := metrics.NewForTest(prometheus.NewRegistry())
|
||||
|
||||
authSvc, appSvc, deploySvc, webhookSvc, dockerClient, auditSvc := createAppServices(
|
||||
t,
|
||||
logInstance,
|
||||
dbInstance,
|
||||
cfg,
|
||||
metricsInstance,
|
||||
)
|
||||
|
||||
handlersInstance, handlerErr := handlers.New(
|
||||
@@ -164,6 +180,7 @@ func setupTestHandlers(t *testing.T) *testContext {
|
||||
Deploy: deploySvc,
|
||||
Webhook: webhookSvc,
|
||||
Docker: dockerClient,
|
||||
Audit: auditSvc,
|
||||
},
|
||||
)
|
||||
require.NoError(t, handlerErr)
|
||||
@@ -173,6 +190,7 @@ func setupTestHandlers(t *testing.T) *testContext {
|
||||
Globals: globalInstance,
|
||||
Config: cfg,
|
||||
Auth: authSvc,
|
||||
Metrics: metricsInstance,
|
||||
})
|
||||
require.NoError(t, mwErr)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user