Documentation
¶
Overview ¶
Package sqlite provides a SQLite-backed implementation of promolog.Storer.
Index ¶
- type Store
- func (s *Store) Aggregate(ctx context.Context, f promolog.AggregateFilter) ([]promolog.AggregateResult, error)
- func (s *Store) AvailableFilters(ctx context.Context, f promolog.TraceFilter) (promolog.FilterOptions, error)
- func (s *Store) CreateRetentionRule(ctx context.Context, rule promolog.RetentionRule) (promolog.RetentionRule, error)
- func (s *Store) CreateRule(ctx context.Context, rule promolog.FilterRule) (promolog.FilterRule, error)
- func (s *Store) DeleteRetentionRule(ctx context.Context, id int) error
- func (s *Store) DeleteRule(ctx context.Context, id int) error
- func (s *Store) DeleteTrace(ctx context.Context, requestID string) error
- func (s *Store) Get(ctx context.Context, requestID string) (*promolog.Trace, error)
- func (s *Store) InitSchema() error
- func (s *Store) ListRetentionRules(ctx context.Context) ([]promolog.RetentionRule, error)
- func (s *Store) ListRules(ctx context.Context) ([]promolog.FilterRule, error)
- func (s *Store) ListTraces(ctx context.Context, f promolog.TraceFilter) ([]promolog.TraceSummary, int, error)
- func (s *Store) LoadRetentionEngine(ctx context.Context) (*promolog.RetentionEngine, error)
- func (s *Store) LoadRuleEngine(ctx context.Context) (*promolog.RuleEngine, error)
- func (s *Store) Promote(ctx context.Context, trace promolog.Trace) error
- func (s *Store) PromoteAt(ctx context.Context, trace promolog.Trace, createdAt time.Time) error
- func (s *Store) SetOnPromote(fn func(promolog.TraceSummary))
- func (s *Store) StartCleanup(ctx context.Context, ttl, interval time.Duration)
- func (s *Store) UpdateRetentionRule(ctx context.Context, rule promolog.RetentionRule) error
- func (s *Store) UpdateRule(ctx context.Context, rule promolog.FilterRule) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a SQLite-backed store of traces.
func NewStore ¶
NewStore creates a Store backed by the given database connection.
Example ¶
package main
import (
"database/sql"
"fmt"
"github.com/catgoose/promolog/sqlite"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", ":memory:")
if err != nil {
panic(err)
}
defer db.Close()
db.SetMaxOpenConns(1)
store := sqlite.NewStore(db)
if err := store.InitSchema(); err != nil {
panic(err)
}
fmt.Println("store ready")
}
Output: store ready
func (*Store) Aggregate ¶
func (s *Store) Aggregate(ctx context.Context, f promolog.AggregateFilter) ([]promolog.AggregateResult, error)
Aggregate groups traces by the field specified in the filter and returns counts along with the top error chains for each group.
func (*Store) AvailableFilters ¶
func (s *Store) AvailableFilters(ctx context.Context, f promolog.TraceFilter) (promolog.FilterOptions, error)
AvailableFilters returns distinct status codes and methods for filter dropdowns.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"github.com/catgoose/promolog"
"github.com/catgoose/promolog/sqlite"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
db.SetMaxOpenConns(1)
store := sqlite.NewStore(db)
_ = store.InitSchema()
ctx := context.Background()
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-1", StatusCode: 400, Route: "/a", Method: "GET",
ErrorChain: "bad request",
})
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-2", StatusCode: 500, Route: "/b", Method: "POST",
ErrorChain: "internal error",
})
// Get distinct values for building filter UI dropdowns.
opts, err := store.AvailableFilters(ctx, promolog.TraceFilter{})
if err != nil {
panic(err)
}
fmt.Println("codes:", opts.StatusCodes)
fmt.Println("methods:", opts.Methods)
}
Output: codes: [400 500] methods: [GET POST]
func (*Store) CreateRetentionRule ¶
func (s *Store) CreateRetentionRule(ctx context.Context, rule promolog.RetentionRule) (promolog.RetentionRule, error)
CreateRetentionRule inserts a new retention rule and returns it with its assigned ID and timestamp.
func (*Store) CreateRule ¶
func (s *Store) CreateRule(ctx context.Context, rule promolog.FilterRule) (promolog.FilterRule, error)
CreateRule inserts a new filter rule and returns it with its assigned ID and timestamp.
func (*Store) DeleteRetentionRule ¶
DeleteRetentionRule removes a retention rule by ID.
func (*Store) DeleteRule ¶
DeleteRule removes a filter rule by ID.
func (*Store) DeleteTrace ¶
DeleteTrace removes a single trace by request ID.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"github.com/catgoose/promolog"
"github.com/catgoose/promolog/sqlite"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
db.SetMaxOpenConns(1)
store := sqlite.NewStore(db)
_ = store.InitSchema()
ctx := context.Background()
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-delete-me", ErrorChain: "gone", StatusCode: 500,
Route: "/api/test", Method: "DELETE",
})
err := store.DeleteTrace(ctx, "req-delete-me")
fmt.Println("delete err:", err)
trace, _ := store.Get(ctx, "req-delete-me")
fmt.Println("after delete:", trace)
}
Output: delete err: <nil> after delete: <nil>
func (*Store) Get ¶
Get returns the full trace for a request ID, or nil if not found.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/catgoose/promolog"
"github.com/catgoose/promolog/sqlite"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
db.SetMaxOpenConns(1)
store := sqlite.NewStore(db)
_ = store.InitSchema()
ctx := context.Background()
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-lookup",
ErrorChain: "timeout",
StatusCode: 504,
Route: "/api/orders",
Method: "POST",
Entries: []promolog.Entry{
{Time: time.Now(), Level: "ERROR", Message: "upstream timeout"},
},
})
// Retrieve the full trace by request ID.
trace, err := store.Get(ctx, "req-lookup")
if err != nil {
panic(err)
}
fmt.Println(trace.Route, trace.StatusCode)
fmt.Println(len(trace.Entries))
// Non-existent request IDs return nil without error.
missing, err := store.Get(ctx, "does-not-exist")
fmt.Println(missing, err)
}
Output: /api/orders 504 1 <nil> <nil>
func (*Store) InitSchema ¶
InitSchema creates the error_traces table if it doesn't exist. It also applies any necessary migrations for existing databases.
func (*Store) ListRetentionRules ¶
ListRetentionRules returns all retention rules ordered by creation time.
func (*Store) ListTraces ¶
func (s *Store) ListTraces(ctx context.Context, f promolog.TraceFilter) ([]promolog.TraceSummary, int, error)
ListTraces returns a page of trace summaries matching the given filters.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"github.com/catgoose/promolog"
"github.com/catgoose/promolog/sqlite"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
db.SetMaxOpenConns(1)
store := sqlite.NewStore(db)
_ = store.InitSchema()
ctx := context.Background()
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-1", ErrorChain: "not found", StatusCode: 404,
Route: "/api/users/99", Method: "GET",
})
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-2", ErrorChain: "db down", StatusCode: 500,
Route: "/api/orders", Method: "POST",
})
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-3", ErrorChain: "bad gateway", StatusCode: 502,
Route: "/api/payments", Method: "POST",
})
// Filter by status class and method.
rows, total, err := store.ListTraces(ctx, promolog.TraceFilter{
Status: "5xx",
Method: "POST",
Sort: "StatusCode",
Dir: "asc",
Page: 1,
PerPage: 10,
})
if err != nil {
panic(err)
}
fmt.Println("total:", total)
for _, r := range rows {
fmt.Printf("%s %d %s\n", r.Route, r.StatusCode, r.Method)
}
}
Output: total: 2 /api/orders 500 POST /api/payments 502 POST
func (*Store) LoadRetentionEngine ¶
LoadRetentionEngine reads all enabled retention rules from the database and returns a ready-to-use RetentionEngine.
func (*Store) LoadRuleEngine ¶
LoadRuleEngine reads all enabled filter rules from the database and returns a ready-to-use RuleEngine.
func (*Store) Promote ¶
Promote persists a trace to the database.
Example ¶
package main
import (
"context"
"database/sql"
"errors"
"fmt"
"time"
"github.com/catgoose/promolog"
"github.com/catgoose/promolog/sqlite"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
db.SetMaxOpenConns(1)
store := sqlite.NewStore(db)
_ = store.InitSchema()
ctx := context.Background()
// Promote persists the buffered log entries when a request fails.
err := store.Promote(ctx, promolog.Trace{
RequestID: "req-abc-123",
ErrorChain: "connection refused",
StatusCode: 502,
Route: "/api/users",
Method: "GET",
UserAgent: "Mozilla/5.0",
RemoteIP: "10.0.0.1",
UserID: "user-42",
Entries: []promolog.Entry{
{Time: time.Now(), Level: "INFO", Message: "starting request"},
{Time: time.Now(), Level: "ERROR", Message: "connection refused", Attrs: map[string]string{"host": "db.local"}},
},
})
fmt.Println(err)
// Promoting the same request ID again returns ErrDuplicateTrace.
err = store.Promote(ctx, promolog.Trace{
RequestID: "req-abc-123",
ErrorChain: "duplicate",
StatusCode: 500,
Route: "/api/users",
Method: "GET",
})
fmt.Println(errors.Is(err, promolog.ErrDuplicateTrace))
}
Output: <nil> true
func (*Store) SetOnPromote ¶
func (s *Store) SetOnPromote(fn func(promolog.TraceSummary))
SetOnPromote registers a callback invoked after each successful promote.
Example ¶
package main
import (
"context"
"database/sql"
"fmt"
"github.com/catgoose/promolog"
"github.com/catgoose/promolog/sqlite"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, _ := sql.Open("sqlite3", ":memory:")
defer db.Close()
db.SetMaxOpenConns(1)
store := sqlite.NewStore(db)
_ = store.InitSchema()
// Register a callback for real-time notifications (SSE, webhooks, etc.).
store.SetOnPromote(func(ts promolog.TraceSummary) {
fmt.Printf("alert: %s %d %s\n", ts.RequestID, ts.StatusCode, ts.Route)
})
ctx := context.Background()
_ = store.Promote(ctx, promolog.Trace{
RequestID: "req-notify",
ErrorChain: "something broke",
StatusCode: 500,
Route: "/api/webhook",
Method: "POST",
})
}
Output: alert: req-notify 500 /api/webhook
func (*Store) StartCleanup ¶
StartCleanup runs a background goroutine that deletes entries older than ttl. If retention rules are configured, traces matching a rule use that rule's TTL instead of the default. The shortest matching TTL wins.
func (*Store) UpdateRetentionRule ¶
UpdateRetentionRule updates an existing retention rule identified by its ID.
func (*Store) UpdateRule ¶
UpdateRule updates an existing filter rule identified by its ID.