Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

logging: respect env vars #58

Merged
merged 3 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions coordinator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package main
import (
"errors"
"fmt"
"log/slog"
"net"
"os"

"github.com/edgelesssys/nunki/internal/ca"
"github.com/edgelesssys/nunki/internal/coordapi"
"github.com/edgelesssys/nunki/internal/intercom"
"github.com/edgelesssys/nunki/internal/logger"
)

func main() {
Expand All @@ -19,7 +19,11 @@ func main() {
}

func run() (retErr error) {
logger := slog.Default()
logger, err := logger.Default()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: creating logger: %v\n", err)
return err
}
defer func() {
if retErr != nil {
logger.Error(retErr.Error())
Expand Down
2 changes: 2 additions & 0 deletions deployments/emojivoto/coordinator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NUNKI_LOG_LEVEL
value: "debug"
---
apiVersion: v1
kind: Service
Expand Down
2 changes: 2 additions & 0 deletions deployments/openssl/coordinator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NUNKI_LOG_LEVEL
value: "debug"
---
apiVersion: v1
kind: Service
Expand Down
2 changes: 2 additions & 0 deletions deployments/simple/coordinator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: NUNKI_LOG_LEVEL
value: "debug"
---
apiVersion: v1
kind: Service
Expand Down
8 changes: 6 additions & 2 deletions initializer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"encoding/pem"
"errors"
"fmt"
"log/slog"
"net"
"os"
"time"
Expand All @@ -20,6 +19,7 @@ import (
"github.com/edgelesssys/nunki/internal/attestation/snp"
"github.com/edgelesssys/nunki/internal/grpc/dialer"
"github.com/edgelesssys/nunki/internal/intercom"
"github.com/edgelesssys/nunki/internal/logger"
)

func main() {
Expand All @@ -29,7 +29,11 @@ func main() {
}

func run() (retErr error) {
logger := slog.Default()
logger, err := logger.Default()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: creating logger: %v\n", err)
return err
}
defer func() {
if retErr != nil {
logger.Error(retErr.Error())
Expand Down
3 changes: 2 additions & 1 deletion internal/attestation/snp/cached_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package snp
import (
"log/slog"

"github.com/edgelesssys/nunki/internal/logger"
"github.com/edgelesssys/nunki/internal/memstore"
"github.com/google/go-sev-guest/verify/trust"
"k8s.io/utils/clock"
Expand All @@ -21,7 +22,7 @@ func newCachedKDSHTTPClient(ticker clock.Ticker, log *slog.Logger) *cachedKDSHTT

c := &cachedKDSHTTPClient{
HTTPSGetter: trust.DefaultHTTPSGetter(),
logger: log.WithGroup("cached-kds-http-client"),
logger: slog.New(logger.NewHandler(log.Handler(), "cached-kds-http-client")),
cache: memstore.New[string, []byte](),
gcTicker: ticker,
}
Expand Down
3 changes: 2 additions & 1 deletion internal/attestation/snp/issuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"fmt"
"log/slog"

"github.com/edgelesssys/nunki/internal/logger"
"github.com/google/go-sev-guest/client"
)

Expand All @@ -24,7 +25,7 @@ type Issuer struct {

// NewIssuer returns a new Issuer.
func NewIssuer(log *slog.Logger) *Issuer {
return &Issuer{logger: log.WithGroup("snp-issuer")}
return &Issuer{logger: slog.New(logger.NewHandler(log.Handler(), "snp-issuer"))}
}

// OID returns the OID of the issuer.
Expand Down
6 changes: 4 additions & 2 deletions internal/attestation/snp/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"fmt"
"log/slog"

"github.com/edgelesssys/nunki/internal/logger"
"github.com/google/go-sev-guest/abi"
"github.com/google/go-sev-guest/proto/sevsnp"
"github.com/google/go-sev-guest/validate"
Expand Down Expand Up @@ -52,9 +53,10 @@ func (v *StaticValidateOptsGenerator) SNPValidateOpts(_ *sevsnp.Report) (*valida

// NewValidator returns a new Validator.
func NewValidator(optsGen validateOptsGenerator, log *slog.Logger) *Validator {
handler := logger.NewHandler(log.Handler(), "snp-validator")
return &Validator{
validateOptsGen: optsGen,
logger: log.WithGroup("snp-validator"),
logger: slog.New(handler),
}
}

Expand All @@ -64,7 +66,7 @@ func NewValidatorWithCallbacks(optsGen validateOptsGenerator, ticker clock.Ticke
validateOptsGen: optsGen,
callbackers: callbacks,
kdsGetter: newCachedKDSHTTPClient(ticker, log),
logger: log.WithGroup("snp-validator"),
logger: slog.New(logger.NewHandler(log.Handler(), "snp-validator")),
}
}

Expand Down
78 changes: 78 additions & 0 deletions internal/logger/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package logger

import (
"context"
"log/slog"
"os"
"strings"
)

// Handler is a slog.Handler that can be used to enable logging on a per-subsystem basis.
type Handler struct {
inner slog.Handler
subsystem string
enabled bool
}

// NewHandler returns a new Handler.
func NewHandler(inner slog.Handler, subsystem string) *Handler {
handler := &Handler{
inner: inner.WithGroup(subsystem),
subsystem: subsystem,
enabled: subsystemEnvEnabled(os.Getenv, subsystem),
}
slog.New(handler).Info("Subsystem logger initialized", "subsystem", subsystem, "state", handler.state())
return handler
}

// Enabled returns true if the given level is enabled.
func (h *Handler) Enabled(ctx context.Context, level slog.Level) bool {
return h.enabled && h.inner.Enabled(ctx, level)
}

// Handle handles the given record.
func (h *Handler) Handle(ctx context.Context, record slog.Record) error {
return h.inner.Handle(ctx, record)
}

// WithAttrs returns a new Handler with the given attributes.
func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler {
return &Handler{
inner: h.inner.WithAttrs(attrs),
subsystem: h.subsystem,
enabled: h.enabled,
}
}

// WithGroup returns a new Handler with the given group.
func (h *Handler) WithGroup(name string) slog.Handler {
return &Handler{
inner: h.inner.WithGroup(name),
subsystem: h.subsystem,
enabled: h.enabled,
}
}

func (h *Handler) state() string {
if h.enabled {
return "enabled"
}
return "disabled"
}

func subsystemEnvEnabled(getEnv func(string) string, subsystem string) bool {
return subsystemAllowListMatch(subsystem, getEnv(LogSubsystems))
}

func subsystemAllowListMatch(subsystem string, allowList string) bool {
if allowList == "*" {
return true
}
for _, allow := range strings.Split(allowList, ",") {
allow = strings.ToLower(strings.TrimSpace(allow))
if allow == subsystem {
return true
}
}
return false
}
109 changes: 109 additions & 0 deletions internal/logger/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package logger

import (
"bytes"
"log/slog"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

func TestHandlerOutput(t *testing.T) {
testCases := map[string]struct {
subsystem string
subsystemEnvList string
wantMessages int
}{
"star": {
subsystem: "foo",
subsystemEnvList: "*",
wantMessages: 2, // message and empty line
},
"match": {
subsystem: "foo",
subsystemEnvList: "foo,bar,baz",
wantMessages: 2, // message and empty line
},
"no match": {
subsystem: "foo",
wantMessages: 1, // empty line
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)

getEnv := newTestGetEnv(map[string]string{
LogSubsystems: tc.subsystemEnvList,
})

buf := bytes.Buffer{}

handler := &Handler{
inner: slog.NewJSONHandler(&buf, nil).WithGroup(tc.subsystem),
subsystem: tc.subsystem,
enabled: subsystemEnvEnabled(getEnv, tc.subsystem),
}
logger := slog.New(handler)

logger.Info("info", "key", "value")

got := buf.String()
lines := strings.Split(got, "\n")
assert.Len(lines, tc.wantMessages)
for _, line := range lines {
if line == "" {
continue
}
assert.Contains(line, tc.subsystem)
}
})
}
}

func TestSubsystemEnvEnabled(t *testing.T) {
testCases := map[string]struct {
subsystem string
subsystemEnvList string
wantEnabled bool
}{
"empty with star": {
subsystem: "",
subsystemEnvList: "*",
wantEnabled: true,
},
"value with star": {
subsystem: "foo",
subsystemEnvList: "*",
wantEnabled: true,
},
"empty list": {
subsystem: "bar",
subsystemEnvList: "",
},
"match": {
subsystem: "bar",
subsystemEnvList: "foo,bar,baz",
wantEnabled: true,
},
"no match": {
subsystem: "bar",
subsystemEnvList: "foo,baz",
},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)

getEnv := newTestGetEnv(map[string]string{
LogSubsystems: tc.subsystemEnvList,
})

got := subsystemEnvEnabled(getEnv, tc.subsystem)
assert.Equal(tc.wantEnabled, got)
})
}
}
Loading