125 lines
2.4 KiB
Go
125 lines
2.4 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
|
|
"datasource/types"
|
|
)
|
|
|
|
type Store struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
func NewStore(dbPath string) (*Store, error) {
|
|
db, err := sql.Open("duckdb", dbPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// keep one connection ready for collector's next tick
|
|
db.SetMaxIdleConns(1)
|
|
|
|
// force sequential access to prevent DuckDB locking errors
|
|
db.SetMaxOpenConns(1)
|
|
|
|
migrationQuery := `
|
|
CREATE TABLE IF NOT EXISTS metrics (
|
|
service VARCHAR,
|
|
timestamp_sec BIGINT,
|
|
up INTEGER,
|
|
uptime_sec BIGINT,
|
|
memory_usage_bytes BIGINT
|
|
)`
|
|
|
|
if _, err := db.Exec(migrationQuery); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Store{db: db}, nil
|
|
}
|
|
|
|
func (s *Store) Close() error {
|
|
return s.db.Close()
|
|
}
|
|
|
|
func (s *Store) SaveMetric(ctx context.Context, metric *types.Metric) error {
|
|
query := `
|
|
INSERT INTO metrics (
|
|
service,
|
|
timestamp_sec,
|
|
up,
|
|
uptime_sec,
|
|
memory_usage_bytes
|
|
) VALUES (?, ?, ?, ?, ?)`
|
|
|
|
_, err := s.db.ExecContext(ctx, query,
|
|
metric.Service,
|
|
metric.TimestampSec,
|
|
metric.Up,
|
|
metric.UptimeSec,
|
|
metric.MemoryUsageBytes,
|
|
)
|
|
|
|
return err
|
|
}
|
|
|
|
func (s *Store) GetMetrics(ctx context.Context, service string, t0, t1 int64) ([]*types.Metric, error) {
|
|
query := `
|
|
SELECT
|
|
timestamp_sec,
|
|
up,
|
|
uptime_sec,
|
|
memory_usage_bytes
|
|
FROM metrics
|
|
WHERE
|
|
service = ? AND
|
|
timestamp_sec BETWEEN ? AND ?
|
|
ORDER BY timestamp_sec`
|
|
|
|
rows, err := s.db.QueryContext(ctx, query, service, t0, t1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var metrics []*types.Metric
|
|
|
|
for rows.Next() {
|
|
metric := &types.Metric{Service: service}
|
|
if err := rows.Scan(&metric.TimestampSec, &metric.Up, &metric.UptimeSec, &metric.MemoryUsageBytes); err != nil {
|
|
return nil, err
|
|
}
|
|
metrics = append(metrics, metric)
|
|
}
|
|
|
|
return metrics, nil
|
|
}
|
|
|
|
func (s *Store) GetAllMetrics(ctx context.Context) ([]*types.Metric, error) {
|
|
query := "SELECT service, timestamp_sec, up, uptime_sec, memory_usage_bytes FROM metrics"
|
|
|
|
rows, err := s.db.QueryContext(ctx, query)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var metrics []*types.Metric
|
|
|
|
for rows.Next() {
|
|
metric := new(types.Metric)
|
|
if err := rows.Scan(&metric.Service, &metric.TimestampSec, &metric.Up, &metric.UptimeSec, &metric.MemoryUsageBytes); err != nil {
|
|
return nil, err
|
|
}
|
|
metrics = append(metrics, metric)
|
|
}
|
|
|
|
return metrics, nil
|
|
}
|
|
|
|
// todo (david)
|
|
// func (s *Store) DeleteMetrics(ctx context.Context, t0, t1 int64) error {
|
|
// return nil
|
|
// }
|