fork of indigo with slightly nicer lexgen

querycheck: switch from zap to log/slog

Changed files
+31 -40
cmd
querycheck
querycheck
+13 -19
cmd/querycheck/main.go
··· 4 "context" 5 "fmt" 6 "log" 7 "os" 8 "os/signal" 9 "sync" ··· 21 22 "github.com/prometheus/client_golang/prometheus/promhttp" 23 "go.opentelemetry.io/otel/trace" 24 - "go.uber.org/zap" 25 26 "github.com/carlmjohnson/versioninfo" 27 "github.com/urfave/cli/v2" ··· 75 signals := make(chan os.Signal, 1) 76 signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) 77 78 - rawlog, err := zap.NewDevelopment() 79 - if err != nil { 80 - log.Fatalf("failed to create logger: %+v\n", err) 81 - } 82 defer func() { 83 - log.Printf("main function teardown\n") 84 - err := rawlog.Sync() 85 - if err != nil { 86 - log.Printf("failed to sync logger on teardown: %+v", err.Error()) 87 - } 88 }() 89 90 - log := rawlog.Sugar().With("source", "querycheck_main") 91 - 92 - log.Info("starting querycheck") 93 94 // Registers a tracer Provider globally if the exporter endpoint is set 95 if os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") != "" { 96 - log.Info("initializing tracer...") 97 shutdown, err := tracing.InstallExportPipeline(ctx, "Querycheck", 1) 98 if err != nil { 99 log.Fatal(err) ··· 153 // Start the metrics server 154 wg.Add(1) 155 go func() { 156 - log.Infof("starting metrics server on port %d", cctx.Int("port")) 157 if err := e.Start(fmt.Sprintf(":%d", cctx.Int("port"))); err != nil { 158 - log.Errorf("failed to start metrics server: %+v\n", err) 159 } 160 wg.Done() 161 }() ··· 168 fmt.Println("shutting down on context done") 169 } 170 171 - log.Info("shutting down, waiting for workers to clean up...") 172 173 if err := e.Shutdown(ctx); err != nil { 174 - log.Errorf("failed to shut down metrics server: %+v\n", err) 175 wg.Done() 176 } 177 178 querychecker.Stop() 179 180 wg.Wait() 181 - log.Info("shut down successfully") 182 183 return nil 184 }
··· 4 "context" 5 "fmt" 6 "log" 7 + "log/slog" 8 "os" 9 "os/signal" 10 "sync" ··· 22 23 "github.com/prometheus/client_golang/prometheus/promhttp" 24 "go.opentelemetry.io/otel/trace" 25 26 "github.com/carlmjohnson/versioninfo" 27 "github.com/urfave/cli/v2" ··· 75 signals := make(chan os.Signal, 1) 76 signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) 77 78 + logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ 79 + Level: slog.LevelInfo, 80 + })) 81 defer func() { 82 + logger.Info("main function teardown") 83 }() 84 85 + logger = logger.With("source", "querycheck_main") 86 + logger.Info("starting querycheck") 87 88 // Registers a tracer Provider globally if the exporter endpoint is set 89 if os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") != "" { 90 + logger.Info("initializing tracer") 91 shutdown, err := tracing.InstallExportPipeline(ctx, "Querycheck", 1) 92 if err != nil { 93 log.Fatal(err) ··· 147 // Start the metrics server 148 wg.Add(1) 149 go func() { 150 + logger.Info("starting metrics serverd", "port", cctx.Int("port")) 151 if err := e.Start(fmt.Sprintf(":%d", cctx.Int("port"))); err != nil { 152 + logger.Error("failed to start metrics server", "err", err) 153 } 154 wg.Done() 155 }() ··· 162 fmt.Println("shutting down on context done") 163 } 164 165 + logger.Info("shutting down, waiting for workers to clean up") 166 167 if err := e.Shutdown(ctx); err != nil { 168 + logger.Error("failed to shut down metrics server", "err", err) 169 wg.Done() 170 } 171 172 querychecker.Stop() 173 174 wg.Wait() 175 + logger.Info("shut down successfully") 176 177 return nil 178 }
+18 -21
querycheck/check.go
··· 2 3 import ( 4 "context" 5 - "log" 6 "math" 7 "sync" 8 "time" 9 10 "github.com/jackc/pgx/v5" 11 "go.opentelemetry.io/otel" 12 "go.opentelemetry.io/otel/attribute" 13 - "go.uber.org/zap" 14 ) 15 16 var tracer = otel.Tracer("querycheck") ··· 33 // Querychecker is a query checker meta object 34 type Querychecker struct { 35 Queries []*Query 36 - Logger *zap.SugaredLogger 37 38 connectionURL string 39 lk sync.RWMutex ··· 41 42 // NewQuerychecker creates a new querychecker 43 func NewQuerychecker(ctx context.Context, connectionURL string) (*Querychecker, error) { 44 - logger, err := zap.NewDevelopment() 45 - if err != nil { 46 - return nil, err 47 - } 48 - l := logger.Sugar().With("source", "querychecker_manager") 49 50 return &Querychecker{ 51 connectionURL: connectionURL, 52 - Logger: l, 53 Queries: []*Query{}, 54 }, nil 55 } ··· 167 168 for _, qu := range q.Queries { 169 go func(query *Query) { 170 - rawlog, err := zap.NewDevelopment() 171 - if err != nil { 172 - log.Fatalf("failed to create logger: %+v\n", err) 173 - } 174 - log := rawlog.Sugar().With("source", "query_checker_routine", "query", query.Name) 175 176 - log.Infof("query checker routine started for query: %s\n", query.Name) 177 - log.Infof("Query: \n%s\n", query.Query) 178 179 // Check the query plan every CheckEvery duration 180 ticker := time.NewTicker(query.CheckEvery) 181 defer ticker.Stop() 182 183 query.LatestPlan, err = q.CheckQueryPlan(ctx, query.Query) 184 if err != nil { 185 - log.Errorf("failed to check query plan: %+v\n", err) 186 } 187 188 if query.LatestPlan != nil { 189 - log.Infof("Initial plan:\n%+v\n", query.LatestPlan.String()) 190 query.RecordPlanMetrics(*query.LatestPlan) 191 query.LastChecked = time.Now() 192 } ··· 211 212 if err != nil || qp == nil { 213 if qp == nil { 214 - log.Errorf("query plan is nil") 215 } 216 - log.Errorf("failed to check query plan: %+v\n", err) 217 errorCounter.WithLabelValues(query.Name).Inc() 218 continue 219 } ··· 231 sign = "-" 232 } 233 234 - log.Infof("query plan has changed (%s%.03fms): \n%+v\n", sign, diff, qp.String()) 235 236 query.lk.Lock() 237 query.PreviousPlan = query.LatestPlan
··· 2 3 import ( 4 "context" 5 + "fmt" 6 + "log/slog" 7 "math" 8 + "os" 9 "sync" 10 "time" 11 12 "github.com/jackc/pgx/v5" 13 "go.opentelemetry.io/otel" 14 "go.opentelemetry.io/otel/attribute" 15 ) 16 17 var tracer = otel.Tracer("querycheck") ··· 34 // Querychecker is a query checker meta object 35 type Querychecker struct { 36 Queries []*Query 37 + Logger *slog.Logger 38 39 connectionURL string 40 lk sync.RWMutex ··· 42 43 // NewQuerychecker creates a new querychecker 44 func NewQuerychecker(ctx context.Context, connectionURL string) (*Querychecker, error) { 45 + logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ 46 + Level: slog.LevelInfo, 47 + })) 48 + logger = logger.With("source", "querychecker_manager") 49 50 return &Querychecker{ 51 connectionURL: connectionURL, 52 + Logger: logger, 53 Queries: []*Query{}, 54 }, nil 55 } ··· 167 168 for _, qu := range q.Queries { 169 go func(query *Query) { 170 + log := q.Logger.With("source", "query_checker_routine", "query", query.Name) 171 172 + log.Info("query checker routine started for query", "query", query.Name) 173 + log.Info(fmt.Sprintf("Query: \n%s\n", query.Query)) 174 175 // Check the query plan every CheckEvery duration 176 ticker := time.NewTicker(query.CheckEvery) 177 defer ticker.Stop() 178 179 + var err error 180 query.LatestPlan, err = q.CheckQueryPlan(ctx, query.Query) 181 if err != nil { 182 + log.Error("failed to check query plan", "err", err) 183 } 184 185 if query.LatestPlan != nil { 186 + log.Info(fmt.Sprintf("Initial plan:\n%+v\n", query.LatestPlan.String())) 187 query.RecordPlanMetrics(*query.LatestPlan) 188 query.LastChecked = time.Now() 189 } ··· 208 209 if err != nil || qp == nil { 210 if qp == nil { 211 + log.Error("query plan is nil") 212 } 213 + log.Error("failed to check query plan", "err", err) 214 errorCounter.WithLabelValues(query.Name).Inc() 215 continue 216 } ··· 228 sign = "-" 229 } 230 231 + log.Info("query plan has changed", "diff", fmt.Sprintf("%s%.03fms", sign, diff), "query_plan", qp.String()) 232 233 query.lk.Lock() 234 query.PreviousPlan = query.LatestPlan