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