Skip to content

Commit 2e57996

Browse files
Merge pull request #3930 from Azure/fix-slog
Moved loggers from instance variables back to usage from context
2 parents 8ce1e24 + 351b1f8 commit 2e57996

File tree

13 files changed

+100
-96
lines changed

13 files changed

+100
-96
lines changed

admin/server/cmd/server/cmd.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ package server
1616

1717
import (
1818
"fmt"
19+
"log/slog"
20+
"os"
1921

22+
"github.com/go-logr/logr"
2023
"github.com/spf13/cobra"
24+
25+
"github.com/Azure/ARO-HCP/internal/utils"
2126
)
2227

2328
func NewCommand() (*cobra.Command, error) {
@@ -37,11 +42,17 @@ func NewCommand() (*cobra.Command, error) {
3742
if err != nil {
3843
return err
3944
}
40-
completed, err := validated.Complete(cmd.Context())
45+
46+
// Create a logr.Logger and add it to context for use throughout the application
47+
handlerOptions := &slog.HandlerOptions{Level: slog.Level(validated.LogVerbosity * -1)}
48+
logrLogger := logr.FromSlogHandler(slog.NewJSONHandler(os.Stdout, handlerOptions))
49+
ctx := utils.ContextWithLogger(cmd.Context(), logrLogger)
50+
51+
completed, err := validated.Complete(ctx)
4152
if err != nil {
4253
return err
4354
}
44-
return completed.Run(cmd.Context())
55+
return completed.Run(ctx)
4556
}
4657

4758
return cmd, nil

admin/server/cmd/server/health.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,54 +15,55 @@
1515
package server
1616

1717
import (
18+
"context"
1819
"fmt"
19-
"log/slog"
2020
"net/http"
2121
"strconv"
2222
"time"
2323

2424
"github.com/Azure/ARO-HCP/admin/server/interrupts"
25+
"github.com/Azure/ARO-HCP/internal/utils"
2526
)
2627

2728
// Health keeps a request multiplexer for health liveness and readiness endpoints
2829
type Health struct {
2930
healthMux *http.ServeMux
30-
logger *slog.Logger
3131
}
3232

3333
// NewHealth creates a new health request multiplexer and starts serving the liveness endpoint
3434
// on the given port
35-
func NewHealthOnPort(logger *slog.Logger, port int) *Health {
35+
func NewHealthOnPort(ctx context.Context, port int) *Health {
36+
logger := utils.LoggerFromContext(ctx)
3637
healthMux := http.NewServeMux()
3738
healthMux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
3839
if _, err := fmt.Fprint(w, "OK"); err != nil {
39-
logger.Error("failed to write health response", "error", err)
40+
logger.Error(err, "failed to write health response")
4041
}
4142
})
4243
server := &http.Server{Addr: ":" + strconv.Itoa(port), Handler: healthMux}
4344
interrupts.ListenAndServe(server, 5*time.Second)
4445
return &Health{
4546
healthMux: healthMux,
46-
logger: logger,
4747
}
4848
}
4949

5050
type ReadinessCheck func() bool
5151

5252
// ServeReady starts serving the readiness endpoint
53-
func (h *Health) ServeReady(readinessChecks ...ReadinessCheck) {
53+
func (h *Health) ServeReady(ctx context.Context, readinessChecks ...ReadinessCheck) {
54+
logger := utils.LoggerFromContext(ctx)
5455
h.healthMux.HandleFunc("/healthz/ready", func(w http.ResponseWriter, r *http.Request) {
5556
for _, readinessCheck := range readinessChecks {
5657
if !readinessCheck() {
5758
w.WriteHeader(http.StatusServiceUnavailable)
5859
if _, err := fmt.Fprint(w, "ReadinessCheck failed"); err != nil {
59-
h.logger.Error("failed to write health response", "error", err)
60+
logger.Error(err, "failed to write health response")
6061
}
6162
return
6263
}
6364
}
6465
if _, err := fmt.Fprint(w, "OK"); err != nil {
65-
h.logger.Error("failed to write health response", "error", err)
66+
logger.Error(err, "failed to write health response")
6667
}
6768
})
6869
}

admin/server/cmd/server/options.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package server
1717
import (
1818
"context"
1919
"fmt"
20-
"log/slog"
2120
"net"
2221
"net/http"
2322
"os"
@@ -38,10 +37,10 @@ import (
3837
"github.com/Azure/ARO-HCP/admin/server/handlers/hcp"
3938
"github.com/Azure/ARO-HCP/admin/server/interrupts"
4039
"github.com/Azure/ARO-HCP/admin/server/middleware"
41-
"github.com/Azure/ARO-HCP/admin/server/pkg/logging"
4240
"github.com/Azure/ARO-HCP/internal/database"
4341
"github.com/Azure/ARO-HCP/internal/fpa"
4442
"github.com/Azure/ARO-HCP/internal/ocm"
43+
"github.com/Azure/ARO-HCP/internal/utils"
4544
)
4645

4746
func DefaultOptions() *RawOptions {
@@ -104,7 +103,6 @@ type completedOptions struct {
104103
DbClient database.DBClient
105104
KustoClient *kusto.Client
106105
FpaCredentialRetriever fpa.FirstPartyApplicationTokenCredentialRetriever
107-
Logger *slog.Logger
108106
}
109107

110108
type Options struct {
@@ -133,8 +131,6 @@ func (o *RawOptions) Validate() (*ValidatedOptions, error) {
133131
}
134132

135133
func (o *ValidatedOptions) Complete(ctx context.Context) (*Options, error) {
136-
logger := logging.New(o.LogVerbosity)
137-
138134
// Create CS client
139135
csConnection, err := sdk.NewUnauthenticatedConnectionBuilder().
140136
URL(o.ClustersServiceURL).
@@ -179,12 +175,12 @@ func (o *ValidatedOptions) Complete(ctx context.Context) (*Options, error) {
179175
}
180176

181177
// Create FPA TokenCredentials with watching and caching
182-
certReader, err := fpa.NewWatchingFileCertificateReader(ctx, o.FpaCertBundlePath, 30*time.Minute, logger)
178+
certReader, err := fpa.NewWatchingFileCertificateReader(ctx, o.FpaCertBundlePath, 30*time.Minute)
183179
if err != nil {
184180
return nil, fmt.Errorf("failed to create certificate reader: %w", err)
185181
}
186182

187-
fpaCredentialRetriever, err := fpa.NewFirstPartyApplicationTokenCredentialRetriever(logger, o.FpaClientID, certReader, azcore.ClientOptions{})
183+
fpaCredentialRetriever, err := fpa.NewFirstPartyApplicationTokenCredentialRetriever(o.FpaClientID, certReader, azcore.ClientOptions{})
188184
if err != nil {
189185
return nil, fmt.Errorf("failed to create the FPA token credentials: %w", err)
190186
}
@@ -198,16 +194,15 @@ func (o *ValidatedOptions) Complete(ctx context.Context) (*Options, error) {
198194
DbClient: dbClient,
199195
KustoClient: kustoClient,
200196
FpaCredentialRetriever: fpaCredentialRetriever,
201-
Logger: logger,
202197
},
203198
}, nil
204199
}
205200

206201
func (opts *Options) Run(ctx context.Context) error {
207-
logger := opts.Logger
202+
logger := utils.LoggerFromContext(ctx)
208203
logger.Info("Reporting health.", "port", opts.HealthPort)
209-
health := NewHealthOnPort(logger, opts.HealthPort)
210-
health.ServeReady(func() bool {
204+
health := NewHealthOnPort(ctx, opts.HealthPort)
205+
health.ServeReady(ctx, func() bool {
211206
// todo: add real readiness checks
212207
return true
213208
})
@@ -225,7 +220,7 @@ func (opts *Options) Run(ctx context.Context) error {
225220

226221
s := http.Server{
227222
Addr: net.JoinHostPort("", strconv.Itoa(opts.Port)),
228-
Handler: middleware.WithClientPrincipal(middleware.WithLowercaseURLPathValue(middleware.WithLogger(logger, rootMux))),
223+
Handler: middleware.WithClientPrincipal(middleware.WithLowercaseURLPathValue(middleware.WithLogger(ctx, rootMux))),
229224
}
230225
interrupts.ListenAndServe(&s, 5*time.Second)
231226
interrupts.WaitForGracefulShutdown()

admin/server/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/Azure/azure-kusto-go v0.16.1
88
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0
99
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0
10+
github.com/go-logr/logr v1.4.3
1011
github.com/openshift-online/ocm-sdk-go v0.1.480
1112
github.com/prometheus/client_golang v1.23.2
1213
github.com/spf13/cobra v1.10.2
@@ -27,7 +28,6 @@ require (
2728
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2829
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
2930
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
30-
github.com/go-logr/logr v1.4.3 // indirect
3131
github.com/go-logr/stdr v1.2.2 // indirect
3232
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
3333
github.com/gogo/protobuf v1.3.2 // indirect

admin/server/interrupts/interrupts.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,28 @@ package interrupts
1717

1818
import (
1919
"context"
20-
"log/slog"
2120
"net/http"
2221
"os"
2322
"os/signal"
2423
"sync"
2524
"syscall"
2625
"time"
2726

28-
"github.com/Azure/ARO-HCP/admin/server/pkg/logging"
27+
"github.com/go-logr/logr"
28+
29+
"github.com/Azure/ARO-HCP/internal/utils"
2930
)
3031

3132
// only one instance of the manager ever exists
3233
var single *manager
3334

3435
// logger is a dedicated logger for the interrupts package, separate from the application logger
3536
// we want this logger to be in place even before main starts running
36-
var logger *slog.Logger
37+
var logger logr.Logger
3738

3839
func init() {
3940
// Initialize a basic logger for interrupts package only
40-
logger = logging.New(0)
41+
logger = utils.DefaultLogger()
4142

4243
m := sync.Mutex{}
4344
single = &manager{
@@ -66,7 +67,7 @@ func handleInterrupt() {
6667
sigChan := signals()
6768
signalsLock.Unlock()
6869
s := <-sigChan
69-
logger.Info("Received signal.", "signal", s)
70+
logger.Info("Received signal", "signal", s)
7071
single.c.L.Lock()
7172
single.seenSignal = true
7273
single.c.Broadcast()
@@ -111,7 +112,7 @@ var gracePeriod = 1 * time.Minute
111112
// blocking.
112113
func WaitForGracefulShutdown() {
113114
wait(func() {
114-
logger.Info("Interrupt received.")
115+
logger.Info("Interrupt received")
115116
})
116117
finished := make(chan struct{})
117118
go func() {
@@ -120,9 +121,9 @@ func WaitForGracefulShutdown() {
120121
}()
121122
select {
122123
case <-finished:
123-
logger.Info("All workers gracefully terminated, exiting.")
124+
logger.Info("All workers gracefully terminated, exiting")
124125
case <-time.After(gracePeriod):
125-
logger.Info("Timed out waiting for workers to gracefully terminate, exiting.")
126+
logger.Info("Timed out waiting for workers to gracefully terminate, exiting")
126127
}
127128
}
128129

@@ -174,9 +175,9 @@ func ListenAndServe(server ListenAndServer, gracePeriod time.Duration) {
174175
defer single.wg.Done()
175176
err := server.ListenAndServe()
176177
if err != nil {
177-
logger.Error("Server exited.", "error", err)
178+
logger.Error(err, "Server exited")
178179
} else {
179-
logger.Info("Server exited.")
180+
logger.Info("Server exited")
180181
}
181182
}()
182183

@@ -193,9 +194,9 @@ func ListenAndServeTLS(server *http.Server, certFile, keyFile string, gracePerio
193194
defer single.wg.Done()
194195
err := server.ListenAndServeTLS(certFile, keyFile)
195196
if err != nil {
196-
logger.Error("Server exited.", "error", err)
197+
logger.Error(err, "Server exited")
197198
} else {
198-
logger.Info("Server exited.")
199+
logger.Info("Server exited")
199200
}
200201
}()
201202

@@ -213,7 +214,7 @@ func shutdown(server Shutdownable, gracePeriod time.Duration) func() {
213214
logger.Info("Server shutting down...")
214215
ctx, cancel := context.WithTimeout(context.Background(), gracePeriod)
215216
if err := server.Shutdown(ctx); err != nil {
216-
logger.Error("Error shutting down server...", "error", err)
217+
logger.Error(err, "Error shutting down server")
217218
}
218219
cancel()
219220
}
@@ -233,7 +234,7 @@ func Tick(work func(), interval func() time.Duration) {
233234
nextInterval := interval()
234235
nextTick := before.Add(nextInterval)
235236
sleep := time.Until(nextTick)
236-
logger.Debug("Resolved next tick interval.",
237+
logger.V(1).Info("Resolved next tick interval",
237238
"before", before,
238239
"interval", nextInterval,
239240
"sleep", sleep,

admin/server/middleware/context.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ const (
4141
contextKeyUrlPathValue = contextKey("url_path.value")
4242
contextKeyHCPResourceID = contextKey("hcp_resource_id")
4343
contextKeyClientPrincipalName = contextKey("client_principal_name")
44-
contextKeyLogger = contextKey("logger")
4544
)
4645

4746
func ContextWithOriginalUrlPathValue(ctx context.Context, originalUrlPathValue string) context.Context {

admin/server/middleware/logger.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,24 @@ package middleware
1616

1717
import (
1818
"context"
19-
"log/slog"
2019
"net/http"
2120
"time"
21+
22+
"github.com/Azure/ARO-HCP/internal/utils"
2223
)
2324

24-
// WithLogger creates a middleware that attaches a logger to the request context.
25-
func WithLogger(logger *slog.Logger, next http.Handler) http.Handler {
25+
// WithLogger creates a middleware that attaches a request-specific logger to the request context.
26+
// It expects the provided context to already have a logger via utils.ContextWithLogger.
27+
func WithLogger(ctx context.Context, next http.Handler) http.Handler {
28+
baseLogger := utils.LoggerFromContext(ctx)
2629
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
2730
start := time.Now()
28-
requestLogger := logger.With("path", request.URL.Path, "method", request.Method)
31+
requestLogger := baseLogger.WithValues("path", request.URL.Path, "method", request.Method)
2932
requestLogger.Info("Got request.")
3033

31-
ctx := context.WithValue(request.Context(), contextKeyLogger, requestLogger)
32-
next.ServeHTTP(writer, request.WithContext(ctx))
34+
requestCtx := utils.ContextWithLogger(request.Context(), requestLogger)
35+
next.ServeHTTP(writer, request.WithContext(requestCtx))
3336

3437
requestLogger.Info("Completed request.", "duration", time.Since(start).String())
3538
})
3639
}
37-
38-
func LoggerFromContext(ctx context.Context) *slog.Logger {
39-
if logger, ok := ctx.Value(contextKeyLogger).(*slog.Logger); ok {
40-
return logger
41-
}
42-
return slog.Default()
43-
}

internal/fpa/token_credential_retriever.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ package fpa
1616

1717
import (
1818
"fmt"
19-
"log/slog"
2019

2120
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
2221
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
@@ -30,13 +29,11 @@ type firstPartyApplicationTokenCredentialRetriever struct {
3029
clientOpts azcore.ClientOptions
3130
clientID string
3231
certReader CertificateReader
33-
logger *slog.Logger
3432
}
3533

36-
func NewFirstPartyApplicationTokenCredentialRetriever(logger *slog.Logger, clientID string, certReader CertificateReader, clientOptions azcore.ClientOptions) (FirstPartyApplicationTokenCredentialRetriever, error) {
34+
func NewFirstPartyApplicationTokenCredentialRetriever(clientID string, certReader CertificateReader, clientOptions azcore.ClientOptions) (FirstPartyApplicationTokenCredentialRetriever, error) {
3735
credentialRetriever := &firstPartyApplicationTokenCredentialRetriever{
3836
clientID: clientID,
39-
logger: logger,
4037
certReader: certReader,
4138
clientOpts: clientOptions,
4239
}

internal/fpa/token_credential_retriever_test.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ package fpa
1717
import (
1818
"crypto"
1919
"crypto/x509"
20-
"log/slog"
21-
"os"
2220
"testing"
2321

2422
"github.com/stretchr/testify/assert"
@@ -53,7 +51,6 @@ func TestCredentialRetrieverLoadsInitialCertificate(t *testing.T) {
5351
}
5452

5553
retriever, err := NewFirstPartyApplicationTokenCredentialRetriever(
56-
slog.New(slog.NewTextHandler(os.Stdout, nil)),
5754
"11111111-1111-1111-1111-111111111111",
5855
mockReader,
5956
azcore.ClientOptions{},

0 commit comments

Comments
 (0)