Add custom logger with source location tracking and remove verbose database logs
- Create internal/logger package with Logger wrapper around slog - Logger automatically adds source file, line number, and function name to all log entries - Use golang.org/x/term to properly detect if stdout is a terminal - Replace all slog.Logger usage with logger.Logger throughout the codebase - Remove verbose logging from database GetStats() method - Update all constructors and dependencies to use the new logger
This commit is contained in:
parent
3f06955214
commit
67f6b78aaa
@ -9,16 +9,14 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/metrics"
|
||||
"git.eeqj.de/sneak/routewatch/internal/streamer"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Set up logger to only show errors
|
||||
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
|
||||
Level: slog.LevelError,
|
||||
}))
|
||||
// Set up logger
|
||||
logger := logger.New()
|
||||
|
||||
// Create metrics tracker
|
||||
metricsTracker := metrics.New()
|
||||
|
1
go.mod
1
go.mod
@ -15,4 +15,5 @@ require (
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
)
|
||||
|
2
go.sum
2
go.sum
@ -24,5 +24,7 @@ go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -5,12 +5,12 @@ import (
|
||||
"database/sql"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/config"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/pkg/asinfo"
|
||||
"github.com/google/uuid"
|
||||
_ "github.com/mattn/go-sqlite3" // CGO SQLite driver
|
||||
@ -24,12 +24,12 @@ const dirPermissions = 0750 // rwxr-x---
|
||||
// Database manages the SQLite database connection and operations.
|
||||
type Database struct {
|
||||
db *sql.DB
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
path string
|
||||
}
|
||||
|
||||
// New creates a new database connection and initializes the schema.
|
||||
func New(cfg *config.Config, logger *slog.Logger) (*Database, error) {
|
||||
func New(cfg *config.Config, logger *logger.Logger) (*Database, error) {
|
||||
dbPath := filepath.Join(cfg.GetStateDir(), "db.sqlite")
|
||||
|
||||
// Log database path
|
||||
@ -348,28 +348,24 @@ func (d *Database) GetStats() (Stats, error) {
|
||||
var stats Stats
|
||||
|
||||
// Count ASNs
|
||||
d.logger.Info("Counting ASNs")
|
||||
err := d.queryRow("SELECT COUNT(*) FROM asns").Scan(&stats.ASNs)
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
|
||||
// Count prefixes
|
||||
d.logger.Info("Counting prefixes")
|
||||
err = d.queryRow("SELECT COUNT(*) FROM prefixes").Scan(&stats.Prefixes)
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
|
||||
// Count IPv4 and IPv6 prefixes
|
||||
d.logger.Info("Counting IPv4 prefixes")
|
||||
const ipVersionV4 = 4
|
||||
err = d.queryRow("SELECT COUNT(*) FROM prefixes WHERE ip_version = ?", ipVersionV4).Scan(&stats.IPv4Prefixes)
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
|
||||
d.logger.Info("Counting IPv6 prefixes")
|
||||
const ipVersionV6 = 6
|
||||
err = d.queryRow("SELECT COUNT(*) FROM prefixes WHERE ip_version = ?", ipVersionV6).Scan(&stats.IPv6Prefixes)
|
||||
if err != nil {
|
||||
@ -377,14 +373,12 @@ func (d *Database) GetStats() (Stats, error) {
|
||||
}
|
||||
|
||||
// Count peerings
|
||||
d.logger.Info("Counting peerings")
|
||||
err = d.queryRow("SELECT COUNT(*) FROM asn_peerings").Scan(&stats.Peerings)
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
|
||||
// Get database file size
|
||||
d.logger.Info("Getting database file size")
|
||||
fileInfo, err := os.Stat(d.path)
|
||||
if err != nil {
|
||||
d.logger.Warn("Failed to get database file size", "error", err)
|
||||
@ -393,7 +387,5 @@ func (d *Database) GetStats() (Stats, error) {
|
||||
stats.FileSizeBytes = fileInfo.Size()
|
||||
}
|
||||
|
||||
d.logger.Info("Stats collection complete")
|
||||
|
||||
return stats, nil
|
||||
}
|
||||
|
@ -3,14 +3,15 @@ package database
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
)
|
||||
|
||||
const slowQueryThreshold = 50 * time.Millisecond
|
||||
|
||||
// logSlowQuery logs queries that take longer than slowQueryThreshold
|
||||
func logSlowQuery(logger *slog.Logger, query string, start time.Time) {
|
||||
func logSlowQuery(logger *logger.Logger, query string, start time.Time) {
|
||||
elapsed := time.Since(start)
|
||||
if elapsed > slowQueryThreshold {
|
||||
logger.Debug("Slow query", "query", query, "duration", elapsed)
|
||||
@ -47,7 +48,7 @@ func (d *Database) exec(query string, args ...interface{}) error {
|
||||
// loggingTx wraps sql.Tx to log slow queries
|
||||
type loggingTx struct {
|
||||
*sql.Tx
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
// QueryRow wraps sql.Tx.QueryRow to log slow queries
|
||||
|
150
internal/logger/logger.go
Normal file
150
internal/logger/logger.go
Normal file
@ -0,0 +1,150 @@
|
||||
// Package logger provides a structured logger with source location tracking
|
||||
package logger
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// Logger wraps slog.Logger to add source location information
|
||||
type Logger struct {
|
||||
*slog.Logger
|
||||
}
|
||||
|
||||
// AsSlog returns the underlying slog.Logger
|
||||
func (l *Logger) AsSlog() *slog.Logger {
|
||||
return l.Logger
|
||||
}
|
||||
|
||||
// New creates a new logger with appropriate handler based on environment
|
||||
func New() *Logger {
|
||||
level := slog.LevelInfo
|
||||
if debug := os.Getenv("DEBUG"); strings.Contains(debug, "routewatch") {
|
||||
level = slog.LevelDebug
|
||||
}
|
||||
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: level,
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
if term.IsTerminal(int(os.Stdout.Fd())) {
|
||||
// Terminal, use text
|
||||
handler = slog.NewTextHandler(os.Stdout, opts)
|
||||
} else {
|
||||
// Not a terminal, use JSON
|
||||
handler = slog.NewJSONHandler(os.Stdout, opts)
|
||||
}
|
||||
|
||||
return &Logger{Logger: slog.New(handler)}
|
||||
}
|
||||
|
||||
const sourceSkipLevel = 2 // Skip levels for source location tracking
|
||||
|
||||
// getSourceAttrs returns attributes for the calling source location
|
||||
func getSourceAttrs() []slog.Attr {
|
||||
pc, file, line, ok := runtime.Caller(sourceSkipLevel)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get just the filename without the full path
|
||||
file = filepath.Base(file)
|
||||
|
||||
// Get the function name
|
||||
fn := runtime.FuncForPC(pc)
|
||||
var funcName string
|
||||
if fn != nil {
|
||||
funcName = filepath.Base(fn.Name())
|
||||
}
|
||||
|
||||
attrs := []slog.Attr{
|
||||
slog.String("source", file),
|
||||
slog.Int("line", line),
|
||||
}
|
||||
|
||||
if funcName != "" {
|
||||
attrs = append(attrs, slog.String("func", funcName))
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
// Debug logs at debug level with source location
|
||||
func (l *Logger) Debug(msg string, args ...any) {
|
||||
sourceAttrs := getSourceAttrs()
|
||||
allArgs := make([]any, 0, len(args)+len(sourceAttrs)*2)
|
||||
|
||||
// Add source attributes first
|
||||
for _, attr := range sourceAttrs {
|
||||
allArgs = append(allArgs, attr)
|
||||
}
|
||||
|
||||
// Add user args
|
||||
allArgs = append(allArgs, args...)
|
||||
|
||||
l.Logger.Debug(msg, allArgs...)
|
||||
}
|
||||
|
||||
// Info logs at info level with source location
|
||||
func (l *Logger) Info(msg string, args ...any) {
|
||||
sourceAttrs := getSourceAttrs()
|
||||
allArgs := make([]any, 0, len(args)+len(sourceAttrs)*2)
|
||||
|
||||
// Add source attributes first
|
||||
for _, attr := range sourceAttrs {
|
||||
allArgs = append(allArgs, attr)
|
||||
}
|
||||
|
||||
// Add user args
|
||||
allArgs = append(allArgs, args...)
|
||||
|
||||
l.Logger.Info(msg, allArgs...)
|
||||
}
|
||||
|
||||
// Warn logs at warn level with source location
|
||||
func (l *Logger) Warn(msg string, args ...any) {
|
||||
sourceAttrs := getSourceAttrs()
|
||||
allArgs := make([]any, 0, len(args)+len(sourceAttrs)*2)
|
||||
|
||||
// Add source attributes first
|
||||
for _, attr := range sourceAttrs {
|
||||
allArgs = append(allArgs, attr)
|
||||
}
|
||||
|
||||
// Add user args
|
||||
allArgs = append(allArgs, args...)
|
||||
|
||||
l.Logger.Warn(msg, allArgs...)
|
||||
}
|
||||
|
||||
// Error logs at error level with source location
|
||||
func (l *Logger) Error(msg string, args ...any) {
|
||||
sourceAttrs := getSourceAttrs()
|
||||
allArgs := make([]any, 0, len(args)+len(sourceAttrs)*2)
|
||||
|
||||
// Add source attributes first
|
||||
for _, attr := range sourceAttrs {
|
||||
allArgs = append(allArgs, attr)
|
||||
}
|
||||
|
||||
// Add user args
|
||||
allArgs = append(allArgs, args...)
|
||||
|
||||
l.Logger.Error(msg, allArgs...)
|
||||
}
|
||||
|
||||
// With returns a new logger with additional attributes
|
||||
func (l *Logger) With(args ...any) *Logger {
|
||||
return &Logger{Logger: l.Logger.With(args...)}
|
||||
}
|
||||
|
||||
// WithGroup returns a new logger with a group prefix
|
||||
func (l *Logger) WithGroup(name string) *Logger {
|
||||
return &Logger{Logger: l.Logger.WithGroup(name)}
|
||||
}
|
@ -5,14 +5,13 @@ package routewatch
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/config"
|
||||
"git.eeqj.de/sneak/routewatch/internal/database"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/metrics"
|
||||
"git.eeqj.de/sneak/routewatch/internal/routingtable"
|
||||
"git.eeqj.de/sneak/routewatch/internal/server"
|
||||
@ -35,7 +34,7 @@ type Dependencies struct {
|
||||
RoutingTable *routingtable.RoutingTable
|
||||
Streamer *streamer.Streamer
|
||||
Server *server.Server
|
||||
Logger *slog.Logger
|
||||
Logger *logger.Logger
|
||||
Config *config.Config
|
||||
}
|
||||
|
||||
@ -46,7 +45,7 @@ type RouteWatch struct {
|
||||
streamer *streamer.Streamer
|
||||
server *server.Server
|
||||
snapshotter *snapshotter.Snapshotter
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
maxRuntime time.Duration
|
||||
shutdown bool
|
||||
mu sync.Mutex
|
||||
@ -229,34 +228,11 @@ func (rw *RouteWatch) logRoutingTableStats(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// NewLogger creates a structured logger
|
||||
func NewLogger() *slog.Logger {
|
||||
level := slog.LevelInfo
|
||||
if debug := os.Getenv("DEBUG"); strings.Contains(debug, "routewatch") {
|
||||
level = slog.LevelDebug
|
||||
}
|
||||
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: level,
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
if os.Stdout.Name() != "/dev/stdout" || os.Getenv("TERM") == "" {
|
||||
// Not a terminal, use JSON
|
||||
handler = slog.NewJSONHandler(os.Stdout, opts)
|
||||
} else {
|
||||
// Terminal, use text
|
||||
handler = slog.NewTextHandler(os.Stdout, opts)
|
||||
}
|
||||
|
||||
return slog.New(handler)
|
||||
}
|
||||
|
||||
// getModule provides all fx dependencies
|
||||
func getModule() fx.Option {
|
||||
return fx.Options(
|
||||
fx.Provide(
|
||||
NewLogger,
|
||||
logger.New,
|
||||
config.New,
|
||||
metrics.New,
|
||||
fx.Annotate(
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/config"
|
||||
"git.eeqj.de/sneak/routewatch/internal/database"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/metrics"
|
||||
"git.eeqj.de/sneak/routewatch/internal/routingtable"
|
||||
"git.eeqj.de/sneak/routewatch/internal/server"
|
||||
@ -164,7 +165,7 @@ func TestRouteWatchLiveFeed(t *testing.T) {
|
||||
mockDB := newMockStore()
|
||||
defer mockDB.Close()
|
||||
|
||||
logger := NewLogger()
|
||||
logger := logger.New()
|
||||
|
||||
// Create metrics tracker
|
||||
metricsTracker := metrics.New()
|
||||
|
@ -1,12 +1,3 @@
|
||||
package routewatch
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewLogger(t *testing.T) {
|
||||
logger := NewLogger()
|
||||
if logger == nil {
|
||||
t.Fatal("NewLogger returned nil")
|
||||
}
|
||||
}
|
||||
// Tests for routewatch package are in app_integration_test.go
|
||||
|
@ -2,12 +2,12 @@ package routewatch
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
@ -21,7 +21,7 @@ func CLIEntry() {
|
||||
app := fx.New(
|
||||
getModule(),
|
||||
fx.StopTimeout(shutdownTimeout), // Allow 60 seconds for graceful shutdown
|
||||
fx.Invoke(func(lc fx.Lifecycle, rw *RouteWatch, logger *slog.Logger) {
|
||||
fx.Invoke(func(lc fx.Lifecycle, rw *RouteWatch, logger *logger.Logger) {
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(_ context.Context) error {
|
||||
go func() {
|
||||
|
@ -1,9 +1,8 @@
|
||||
package routewatch
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/database"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/ristypes"
|
||||
)
|
||||
|
||||
@ -15,13 +14,13 @@ const (
|
||||
// DatabaseHandler handles BGP messages and stores them in the database
|
||||
type DatabaseHandler struct {
|
||||
db database.Store
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
// NewDatabaseHandler creates a new database handler
|
||||
func NewDatabaseHandler(
|
||||
db database.Store,
|
||||
logger *slog.Logger,
|
||||
logger *logger.Logger,
|
||||
) *DatabaseHandler {
|
||||
return &DatabaseHandler{
|
||||
db: db,
|
||||
|
@ -1,11 +1,11 @@
|
||||
package routewatch
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/database"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/ristypes"
|
||||
)
|
||||
|
||||
@ -23,7 +23,7 @@ const (
|
||||
// BatchedDatabaseHandler handles BGP messages and stores them in the database using batched operations
|
||||
type BatchedDatabaseHandler struct {
|
||||
db database.Store
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
|
||||
// Batching
|
||||
mu sync.Mutex
|
||||
@ -54,7 +54,7 @@ type peeringOp struct {
|
||||
// NewBatchedDatabaseHandler creates a new batched database handler
|
||||
func NewBatchedDatabaseHandler(
|
||||
db database.Store,
|
||||
logger *slog.Logger,
|
||||
logger *logger.Logger,
|
||||
) *BatchedDatabaseHandler {
|
||||
h := &BatchedDatabaseHandler{
|
||||
db: db,
|
||||
|
@ -1,19 +1,23 @@
|
||||
package routewatch
|
||||
|
||||
import (
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/ristypes"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
// SimpleHandler is a basic implementation of streamer.MessageHandler
|
||||
type SimpleHandler struct {
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
messageTypes []string
|
||||
callback func(*ristypes.RISMessage)
|
||||
}
|
||||
|
||||
// NewSimpleHandler creates a handler that accepts specific message types
|
||||
func NewSimpleHandler(logger *slog.Logger, messageTypes []string, callback func(*ristypes.RISMessage)) *SimpleHandler {
|
||||
func NewSimpleHandler(
|
||||
logger *logger.Logger,
|
||||
messageTypes []string,
|
||||
callback func(*ristypes.RISMessage),
|
||||
) *SimpleHandler {
|
||||
return &SimpleHandler{
|
||||
logger: logger,
|
||||
messageTypes: messageTypes,
|
||||
|
@ -1,10 +1,10 @@
|
||||
package routewatch
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"strconv"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/database"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/ristypes"
|
||||
)
|
||||
|
||||
@ -16,11 +16,11 @@ const (
|
||||
// PeerHandler tracks BGP peers from all message types
|
||||
type PeerHandler struct {
|
||||
db database.Store
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
// NewPeerHandler creates a new peer tracking handler
|
||||
func NewPeerHandler(db database.Store, logger *slog.Logger) *PeerHandler {
|
||||
func NewPeerHandler(db database.Store, logger *logger.Logger) *PeerHandler {
|
||||
return &PeerHandler{
|
||||
db: db,
|
||||
logger: logger,
|
||||
|
@ -1,12 +1,12 @@
|
||||
package routewatch
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/database"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/ristypes"
|
||||
)
|
||||
|
||||
@ -24,7 +24,7 @@ const (
|
||||
// BatchedPeerHandler tracks BGP peers from all message types using batched operations
|
||||
type BatchedPeerHandler struct {
|
||||
db database.Store
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
|
||||
// Batching
|
||||
mu sync.Mutex
|
||||
@ -42,7 +42,7 @@ type peerUpdate struct {
|
||||
}
|
||||
|
||||
// NewBatchedPeerHandler creates a new batched peer tracking handler
|
||||
func NewBatchedPeerHandler(db database.Store, logger *slog.Logger) *BatchedPeerHandler {
|
||||
func NewBatchedPeerHandler(db database.Store, logger *logger.Logger) *BatchedPeerHandler {
|
||||
h := &BatchedPeerHandler{
|
||||
db: db,
|
||||
logger: logger,
|
||||
|
@ -1,9 +1,9 @@
|
||||
package routewatch
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"strconv"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/ristypes"
|
||||
"git.eeqj.de/sneak/routewatch/internal/routingtable"
|
||||
"github.com/google/uuid"
|
||||
@ -17,11 +17,11 @@ const (
|
||||
// RoutingTableHandler handles BGP messages and updates the in-memory routing table
|
||||
type RoutingTableHandler struct {
|
||||
rt *routingtable.RoutingTable
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
}
|
||||
|
||||
// NewRoutingTableHandler creates a new routing table handler
|
||||
func NewRoutingTableHandler(rt *routingtable.RoutingTable, logger *slog.Logger) *RoutingTableHandler {
|
||||
func NewRoutingTableHandler(rt *routingtable.RoutingTable, logger *logger.Logger) *RoutingTableHandler {
|
||||
return &RoutingTableHandler{
|
||||
rt: rt,
|
||||
logger: logger,
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@ -14,6 +13,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/config"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@ -68,7 +68,7 @@ type RoutingTable struct {
|
||||
}
|
||||
|
||||
// New creates a new routing table, loading from snapshot if available
|
||||
func New(cfg *config.Config, logger *slog.Logger) *RoutingTable {
|
||||
func New(cfg *config.Config, logger *logger.Logger) *RoutingTable {
|
||||
rt := &RoutingTable{
|
||||
routes: make(map[RouteKey]*Route),
|
||||
byPrefix: make(map[uuid.UUID]map[RouteKey]*Route),
|
||||
@ -452,7 +452,7 @@ func isIPv6(prefix string) bool {
|
||||
}
|
||||
|
||||
// loadFromSnapshot attempts to load the routing table from a snapshot file
|
||||
func (rt *RoutingTable) loadFromSnapshot(logger *slog.Logger) error {
|
||||
func (rt *RoutingTable) loadFromSnapshot(logger *logger.Logger) error {
|
||||
// If no snapshot directory specified, nothing to load
|
||||
if rt.snapshotDir == "" {
|
||||
return nil
|
||||
|
@ -1,18 +1,18 @@
|
||||
package routingtable
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/config"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func TestRoutingTable(t *testing.T) {
|
||||
// Create a test logger
|
||||
logger := slog.Default()
|
||||
logger := logger.New()
|
||||
|
||||
// Create test config with empty state dir (no snapshot loading)
|
||||
cfg := &config.Config{
|
||||
@ -129,7 +129,7 @@ func TestRoutingTable(t *testing.T) {
|
||||
|
||||
func TestRoutingTableConcurrency(t *testing.T) {
|
||||
// Create a test logger
|
||||
logger := slog.Default()
|
||||
logger := logger.New()
|
||||
|
||||
// Create test config with empty state dir (no snapshot loading)
|
||||
cfg := &config.Config{
|
||||
@ -189,7 +189,7 @@ func TestRoutingTableConcurrency(t *testing.T) {
|
||||
|
||||
func TestRouteUpdate(t *testing.T) {
|
||||
// Create a test logger
|
||||
logger := slog.Default()
|
||||
logger := logger.New()
|
||||
|
||||
// Create test config with empty state dir (no snapshot loading)
|
||||
cfg := &config.Config{
|
||||
|
@ -4,12 +4,12 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/database"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/routingtable"
|
||||
"git.eeqj.de/sneak/routewatch/internal/streamer"
|
||||
"git.eeqj.de/sneak/routewatch/internal/templates"
|
||||
@ -23,12 +23,12 @@ type Server struct {
|
||||
db database.Store
|
||||
routingTable *routingtable.RoutingTable
|
||||
streamer *streamer.Streamer
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
srv *http.Server
|
||||
}
|
||||
|
||||
// New creates a new HTTP server
|
||||
func New(db database.Store, rt *routingtable.RoutingTable, streamer *streamer.Streamer, logger *slog.Logger) *Server {
|
||||
func New(db database.Store, rt *routingtable.RoutingTable, streamer *streamer.Streamer, logger *logger.Logger) *Server {
|
||||
s := &Server{
|
||||
db: db,
|
||||
routingTable: rt,
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
@ -27,7 +27,7 @@ const (
|
||||
type Snapshotter struct {
|
||||
rt *routingtable.RoutingTable
|
||||
stateDir string
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
mu sync.Mutex // Ensures only one snapshot runs at a time
|
||||
@ -36,7 +36,7 @@ type Snapshotter struct {
|
||||
}
|
||||
|
||||
// New creates a new Snapshotter instance
|
||||
func New(rt *routingtable.RoutingTable, cfg *config.Config, logger *slog.Logger) (*Snapshotter, error) {
|
||||
func New(rt *routingtable.RoutingTable, cfg *config.Config, logger *logger.Logger) (*Snapshotter, error) {
|
||||
stateDir := cfg.GetStateDir()
|
||||
|
||||
// If state directory is specified, ensure it exists
|
||||
|
@ -7,13 +7,13 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/metrics"
|
||||
"git.eeqj.de/sneak/routewatch/internal/ristypes"
|
||||
)
|
||||
@ -63,7 +63,7 @@ type handlerInfo struct {
|
||||
|
||||
// Streamer handles streaming BGP updates from RIS Live
|
||||
type Streamer struct {
|
||||
logger *slog.Logger
|
||||
logger *logger.Logger
|
||||
client *http.Client
|
||||
handlers []*handlerInfo
|
||||
rawHandler RawMessageHandler
|
||||
@ -75,7 +75,7 @@ type Streamer struct {
|
||||
}
|
||||
|
||||
// New creates a new RIS streamer
|
||||
func New(logger *slog.Logger, metrics *metrics.Tracker) *Streamer {
|
||||
func New(logger *logger.Logger, metrics *metrics.Tracker) *Streamer {
|
||||
return &Streamer{
|
||||
logger: logger,
|
||||
client: &http.Client{
|
||||
|
@ -3,12 +3,12 @@ package streamer
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.eeqj.de/sneak/routewatch/internal/logger"
|
||||
"git.eeqj.de/sneak/routewatch/internal/metrics"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
func TestNewStreamer(t *testing.T) {
|
||||
logger := slog.Default()
|
||||
logger := logger.New()
|
||||
metricsTracker := metrics.New()
|
||||
s := New(logger, metricsTracker)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user