docs(runtime-logs): implement runtime log management features
Добавлены новые возможности для работы с файловыми логами Docker-сервисов: - Эндпоинты для получения списка логов и хвоста лог-файла. - Очистка лог-файлов с возможностью выбора режима (truncate или delete) и запись в аудит очистки. - Обновлена документация и конфигурация для поддержки новых функций. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"evobgp/internal/store"
|
||||
)
|
||||
|
||||
// AppendRuntimeLogCleanupAudit records a runtime log cleanup operation.
|
||||
func (p *Postgres) AppendRuntimeLogCleanupAudit(tenantID, actor, filename, action string, sizeBefore int64, sizeAfter *int64, detail map[string]any) (string, error) {
|
||||
if strings.TrimSpace(tenantID) == "" || !store.ValidRuntimeLogCleanupAction(action) || strings.TrimSpace(filename) == "" {
|
||||
return "", store.ErrInvalidInput
|
||||
}
|
||||
ctx := context.Background()
|
||||
id := uuid.NewString()
|
||||
var detailJSON []byte
|
||||
if detail != nil {
|
||||
detailJSON, _ = json.Marshal(detail)
|
||||
}
|
||||
var sizeAfterVal any
|
||||
if sizeAfter != nil {
|
||||
sizeAfterVal = *sizeAfter
|
||||
}
|
||||
_, err := p.pool.Exec(ctx, `
|
||||
INSERT INTO runtime_log_cleanup_audit
|
||||
(id, tenant_id, actor_prefix, filename, action, size_before, size_after, detail_json, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, now())`,
|
||||
id, tenantID, strings.TrimSpace(actor), strings.TrimSpace(filename), action,
|
||||
sizeBefore, sizeAfterVal, nullJSONBytes(detailJSON))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// ListRuntimeLogCleanupAudit returns paginated cleanup audit rows for a tenant.
|
||||
func (p *Postgres) ListRuntimeLogCleanupAudit(tenantID, cursor string, limit int) ([]*store.RuntimeLogCleanupAudit, string, bool, error) {
|
||||
if limit <= 0 {
|
||||
limit = 50
|
||||
}
|
||||
off := 0
|
||||
if cursor != "" {
|
||||
if n, err := strconv.Atoi(cursor); err == nil && n >= 0 {
|
||||
off = n
|
||||
}
|
||||
}
|
||||
ctx := context.Background()
|
||||
rows, err := p.pool.Query(ctx, `
|
||||
SELECT id, tenant_id, actor_prefix, filename, action, size_before, size_after, detail_json, created_at
|
||||
FROM runtime_log_cleanup_audit
|
||||
WHERE tenant_id = $1
|
||||
ORDER BY created_at DESC, id DESC
|
||||
LIMIT $2 OFFSET $3`, tenantID, limit+1, off)
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []*store.RuntimeLogCleanupAudit
|
||||
for rows.Next() {
|
||||
var r store.RuntimeLogCleanupAudit
|
||||
var detailRaw []byte
|
||||
var sizeAfter *int64
|
||||
if err := rows.Scan(&r.ID, &r.TenantID, &r.ActorPrefix, &r.Filename, &r.Action,
|
||||
&r.SizeBefore, &sizeAfter, &detailRaw, &r.CreatedAt); err != nil {
|
||||
continue
|
||||
}
|
||||
r.SizeAfter = sizeAfter
|
||||
if len(detailRaw) > 0 {
|
||||
_ = json.Unmarshal(detailRaw, &r.Detail)
|
||||
}
|
||||
out = append(out, &r)
|
||||
}
|
||||
more := len(out) > limit
|
||||
if more {
|
||||
out = out[:limit]
|
||||
}
|
||||
next := ""
|
||||
if more {
|
||||
next = strconv.Itoa(off + limit)
|
||||
}
|
||||
return out, next, more, rows.Err()
|
||||
}
|
||||
Reference in New Issue
Block a user