Skip to content

Commit 953d714

Browse files
committed
refactor: introduce structured logging abstraction
1 parent ec6accb commit 953d714

File tree

5 files changed

+110
-16
lines changed

5 files changed

+110
-16
lines changed

cmd/pulse/main.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ package main
22

33
import (
44
"context"
5-
"log"
65
"os"
76
"os/signal"
87
"syscall"
98

109
"github.com/joho/godotenv"
1110

11+
"github.com/pixel365/pulse/internal/logger"
12+
1213
checkrepo "github.com/pixel365/pulse/internal/repository/check"
1314
checksvc "github.com/pixel365/pulse/internal/services/check"
1415

@@ -17,23 +18,22 @@ import (
1718
"github.com/pixel365/pulse/internal/config"
1819
)
1920

20-
func init() {
21-
_ = godotenv.Load()
22-
}
23-
2421
func main() {
2522
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
2623
defer stop()
2724

28-
cfg := config.MustLoad()
25+
_ = godotenv.Load()
2926

27+
cfg := config.MustLoad()
28+
log := logger.NewSlog()
3029
repo := checkrepo.NewStateRepository()
3130
stateSvc := checksvc.NewStateService(repo)
3231
checkHandlerSvc := checksvc.NewHandlerService(stateSvc)
3332

34-
runner := app.NewApp(cfg, checkHandlerSvc)
33+
runner := app.NewApp(cfg, log, checkHandlerSvc)
3534
if err := runner.Run(ctx); err != nil {
3635
stop()
37-
log.Fatalf("app run error: %v", err)
36+
log.Error(ctx, "failed to run app", "error", err)
37+
os.Exit(1)
3838
}
3939
}

internal/app/app.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55

66
"golang.org/x/sync/errgroup"
77

8+
"github.com/pixel365/pulse/internal/logger"
9+
810
checksvc "github.com/pixel365/pulse/internal/services/check"
911

1012
"github.com/pixel365/pulse/internal"
@@ -22,52 +24,74 @@ var _ internal.Runner = (*App)(nil)
2224
type App struct {
2325
cfg *config.Config
2426
checkHandlerSvc checksvc.CheckHandlerService
27+
logger logger.Logger
2528
}
2629

27-
func NewApp(cfg *config.Config, checkSvc checksvc.CheckHandlerService) *App {
30+
func NewApp(cfg *config.Config, logger logger.Logger, checkSvc checksvc.CheckHandlerService) *App {
2831
return &App{
2932
cfg: cfg,
3033
checkHandlerSvc: checkSvc,
34+
logger: logger,
3135
}
3236
}
3337

3438
func (a *App) Run(ctx context.Context) error {
3539
g, ctx := errgroup.WithContext(ctx)
3640

3741
for i := range a.cfg.HttpChecks {
38-
executor := internal.NewCheckExecutor(a.checkHandlerSvc, a.cfg.HttpChecks[i].CheckFields)
42+
executor := internal.NewCheckExecutor(
43+
a.checkHandlerSvc,
44+
a.cfg.HttpChecks[i].CheckFields,
45+
a.logger,
46+
)
3947
checker := http.NewChecker(a.cfg.HttpChecks[i], executor)
4048
g.Go(func() error {
4149
return checker.Check(ctx)
4250
})
4351
}
4452

4553
for i := range a.cfg.TCPChecks {
46-
executor := internal.NewCheckExecutor(a.checkHandlerSvc, a.cfg.TCPChecks[i].CheckFields)
54+
executor := internal.NewCheckExecutor(
55+
a.checkHandlerSvc,
56+
a.cfg.TCPChecks[i].CheckFields,
57+
a.logger,
58+
)
4759
checker := tcp.NewChecker(a.cfg.TCPChecks[i], executor)
4860
g.Go(func() error {
4961
return checker.Check(ctx)
5062
})
5163
}
5264

5365
for i := range a.cfg.GRPCChecks {
54-
executor := internal.NewCheckExecutor(a.checkHandlerSvc, a.cfg.GRPCChecks[i].CheckFields)
66+
executor := internal.NewCheckExecutor(
67+
a.checkHandlerSvc,
68+
a.cfg.GRPCChecks[i].CheckFields,
69+
a.logger,
70+
)
5571
checker := grpc.NewChecker(a.cfg.GRPCChecks[i], executor)
5672
g.Go(func() error {
5773
return checker.Check(ctx)
5874
})
5975
}
6076

6177
for i := range a.cfg.DNSChecks {
62-
executor := internal.NewCheckExecutor(a.checkHandlerSvc, a.cfg.DNSChecks[i].CheckFields)
78+
executor := internal.NewCheckExecutor(
79+
a.checkHandlerSvc,
80+
a.cfg.DNSChecks[i].CheckFields,
81+
a.logger,
82+
)
6383
checker := dns.NewChecker(a.cfg.DNSChecks[i], executor)
6484
g.Go(func() error {
6585
return checker.Check(ctx)
6686
})
6787
}
6888

6989
for i := range a.cfg.TLSChecks {
70-
executor := internal.NewCheckExecutor(a.checkHandlerSvc, a.cfg.TLSChecks[i].CheckFields)
90+
executor := internal.NewCheckExecutor(
91+
a.checkHandlerSvc,
92+
a.cfg.TLSChecks[i].CheckFields,
93+
a.logger,
94+
)
7195
checker := tls.NewChecker(a.cfg.TLSChecks[i], executor)
7296
g.Go(func() error {
7397
return checker.Check(ctx)

internal/executor.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/pixel365/pulse/internal/config"
99
"github.com/pixel365/pulse/internal/e"
10+
"github.com/pixel365/pulse/internal/logger"
1011
"github.com/pixel365/pulse/internal/model"
1112
"github.com/pixel365/pulse/internal/services/check"
1213
)
@@ -19,6 +20,7 @@ var _ CheckExecutor = (*CheckExec)(nil)
1920

2021
type CheckExec struct {
2122
handler check.CheckHandlerService
23+
logger logger.Logger
2224
cfg config.CheckFields
2325
}
2426

@@ -47,9 +49,8 @@ func (c *CheckExec) Execute(
4749
SuccessThreshold: c.cfg.SuccessThreshold,
4850
}
4951

50-
//nolint:staticcheck
5152
if err := c.handler.Handle(ctx, policy, result); err != nil {
52-
//TODO: log
53+
c.logger.Error(ctx, "failed to handle check result", "error", err)
5354
}
5455
}
5556
}
@@ -104,9 +105,11 @@ func (c *CheckExec) execute(
104105
func NewCheckExecutor(
105106
handler check.CheckHandlerService,
106107
cfg config.CheckFields,
108+
logger logger.Logger,
107109
) *CheckExec {
108110
return &CheckExec{
109111
handler: handler,
110112
cfg: cfg,
113+
logger: logger,
111114
}
112115
}

internal/logger/logger.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package logger
2+
3+
import (
4+
"context"
5+
)
6+
7+
type Logger interface {
8+
Debug(context.Context, string, ...any)
9+
Info(context.Context, string, ...any)
10+
Warn(context.Context, string, ...any)
11+
Error(context.Context, string, ...any)
12+
}

internal/logger/slog.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package logger
2+
3+
import (
4+
"context"
5+
"log/slog"
6+
"os"
7+
"strconv"
8+
)
9+
10+
var _ Logger = (*Slog)(nil)
11+
12+
type Slog struct {
13+
logger *slog.Logger
14+
debug bool
15+
}
16+
17+
func (l *Slog) Debug(ctx context.Context, msg string, args ...any) {
18+
if l == nil || !l.debug {
19+
return
20+
}
21+
22+
l.logger.DebugContext(ctx, msg, args...)
23+
}
24+
25+
func (l *Slog) Info(ctx context.Context, msg string, args ...any) {
26+
if l == nil {
27+
return
28+
}
29+
30+
l.logger.InfoContext(ctx, msg, args...)
31+
}
32+
33+
func (l *Slog) Warn(ctx context.Context, msg string, args ...any) {
34+
if l == nil {
35+
return
36+
}
37+
38+
l.logger.WarnContext(ctx, msg, args...)
39+
}
40+
41+
func (l *Slog) Error(ctx context.Context, msg string, args ...any) {
42+
if l == nil {
43+
return
44+
}
45+
46+
l.logger.ErrorContext(ctx, msg, args...)
47+
}
48+
49+
func NewSlog() *Slog {
50+
debug, _ := strconv.ParseBool(os.Getenv("DEBUG"))
51+
return &Slog{
52+
logger: slog.New(slog.NewJSONHandler(os.Stdout, nil)),
53+
debug: debug,
54+
}
55+
}

0 commit comments

Comments
 (0)