Files
HellreigN/backend/internal/repository/log_repository.go
T
d3m0k1d d96f952d73
ci-agent / build (push) Failing after 22s
chore: add clickhouse as db for logs on agent and search
2026-04-03 23:23:43 +03:00

179 lines
4.0 KiB
Go

package repository
import (
"context"
"time"
"gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/storage"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
)
type LogRepository struct {
Conn driver.Conn
}
func NewLogRepository(conn driver.Conn) *LogRepository {
return &LogRepository{Conn: conn}
}
func (r *LogRepository) Init(ctx context.Context) error {
return r.Conn.Exec(ctx, storage.CreateLogsTable)
}
func (r *LogRepository) Insert(ctx context.Context, log storage.LogEntry) error {
return r.Conn.Exec(ctx, `
INSERT INTO logs (timestamp, level, service, agent, message)
VALUES ($1, $2, $3, $4, $5)
`, log.Timestamp, log.Level, log.Service, log.Agent, log.Message)
}
func (r *LogRepository) InsertBatch(ctx context.Context, logs []storage.LogEntry) error {
batch, err := r.Conn.PrepareBatch(ctx, "INSERT INTO logs (timestamp, level, service, agent, message)")
if err != nil {
return err
}
for _, log := range logs {
if err := batch.Append(log.Timestamp, log.Level, log.Service, log.Agent, log.Message); err != nil {
return err
}
}
return batch.Send()
}
type LogFilter struct {
Level string
Service string
Agent string
DateFrom time.Time
DateTo time.Time
Limit int
Offset int
}
func (r *LogRepository) Search(ctx context.Context, filter LogFilter) ([]storage.LogEntry, error) {
query := "SELECT timestamp, level, service, agent, message FROM logs WHERE 1=1"
args := make([]interface{}, 0)
argIdx := 1
if filter.Level != "" {
query += " AND level = $" + string(rune('0'+argIdx))
args = append(args, filter.Level)
argIdx++
}
if filter.Service != "" {
query += " AND service = $" + string(rune('0'+argIdx))
args = append(args, filter.Service)
argIdx++
}
if filter.Agent != "" {
query += " AND agent = $" + string(rune('0'+argIdx))
args = append(args, filter.Agent)
argIdx++
}
if !filter.DateFrom.IsZero() {
query += " AND timestamp >= $" + string(rune('0'+argIdx))
args = append(args, filter.DateFrom)
argIdx++
}
if !filter.DateTo.IsZero() {
query += " AND timestamp <= $" + string(rune('0'+argIdx))
args = append(args, filter.DateTo)
argIdx++
}
query += " ORDER BY timestamp DESC"
if filter.Limit > 0 {
query += " LIMIT $" + string(rune('0'+argIdx))
args = append(args, filter.Limit)
argIdx++
} else {
query += " LIMIT 100"
}
if filter.Offset > 0 {
query += " OFFSET $" + string(rune('0'+argIdx))
args = append(args, filter.Offset)
}
rows, err := r.Conn.Query(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var logs []storage.LogEntry
for rows.Next() {
var log storage.LogEntry
if err := rows.Scan(&log.Timestamp, &log.Level, &log.Service, &log.Agent, &log.Message); err != nil {
return nil, err
}
logs = append(logs, log)
}
return logs, rows.Err()
}
func (r *LogRepository) GetDistinctServices(ctx context.Context) ([]string, error) {
rows, err := r.Conn.Query(ctx, "SELECT DISTINCT service FROM logs ORDER BY service")
if err != nil {
return nil, err
}
defer rows.Close()
var services []string
for rows.Next() {
var service string
if err := rows.Scan(&service); err != nil {
return nil, err
}
services = append(services, service)
}
return services, rows.Err()
}
func (r *LogRepository) GetDistinctAgents(ctx context.Context) ([]string, error) {
rows, err := r.Conn.Query(ctx, "SELECT DISTINCT agent FROM logs ORDER BY agent")
if err != nil {
return nil, err
}
defer rows.Close()
var agents []string
for rows.Next() {
var agent string
if err := rows.Scan(&agent); err != nil {
return nil, err
}
agents = append(agents, agent)
}
return agents, rows.Err()
}
func (r *LogRepository) GetDistinctLevels(ctx context.Context) ([]string, error) {
rows, err := r.Conn.Query(ctx, "SELECT DISTINCT level FROM logs ORDER BY level")
if err != nil {
return nil, err
}
defer rows.Close()
var levels []string
for rows.Next() {
var level string
if err := rows.Scan(&level); err != nil {
return nil, err
}
levels = append(levels, level)
}
return levels, rows.Err()
}