Skip to content
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
3 changes: 3 additions & 0 deletions changes/unreleased/Added-20260303-092813.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kind: Added
body: Added ability to configure per-component log levels.
time: 2026-03-03T09:28:13.225331-05:00
65 changes: 40 additions & 25 deletions docs/installation/configuration.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions server/internal/api/provide.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package api
import (
"fmt"

"github.com/rs/zerolog"
"github.com/samber/do"

"github.com/pgEdge/control-plane/server/internal/api/apiv1"
"github.com/pgEdge/control-plane/server/internal/config"
"github.com/pgEdge/control-plane/server/internal/logging"
)

func Provide(i *do.Injector) {
Expand All @@ -21,14 +21,14 @@ func provideServer(i *do.Injector) {
if err != nil {
return nil, fmt.Errorf("failed to get config: %w", err)
}
logger, err := do.Invoke[zerolog.Logger](i)
loggerFactory, err := do.Invoke[*logging.Factory](i)
if err != nil {
return nil, fmt.Errorf("failed to get logger: %w", err)
return nil, fmt.Errorf("failed to get logger factory: %w", err)
}
v1Svc, err := do.Invoke[*apiv1.Service](i)
if err != nil {
return nil, fmt.Errorf("failed to get v1 api service: %w", err)
}
return NewServer(cfg, logger, v1Svc), nil
return NewServer(cfg, loggerFactory, v1Svc), nil
})
}
8 changes: 3 additions & 5 deletions server/internal/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/pgEdge/control-plane/server/internal/api/apiv1"
"github.com/pgEdge/control-plane/server/internal/config"
"github.com/pgEdge/control-plane/server/internal/logging"
)

var _ do.Shutdownable = (*Server)(nil)
Expand All @@ -28,7 +29,7 @@ type Server struct {

func NewServer(
cfg config.Config,
logger zerolog.Logger,
loggerFactory *logging.Factory,
v1Svc *apiv1.Service,
) *Server {
mux := goahttp.NewMuxer()
Expand All @@ -45,10 +46,7 @@ func NewServer(
// Mount all the v1 handlers
v1Svc.Mount(mux)

logger = logger.With().
Str("component", "api_server").
Logger()

logger := loggerFactory.Logger("api_server")
handler := addMiddleware(logger, mux)

var (
Expand Down
5 changes: 3 additions & 2 deletions server/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ func validateOptionalID(name, value string) error {
}

type Logging struct {
Level string `koanf:"level" json:"level,omitempty"`
Pretty bool `koanf:"pretty" json:"pretty,omitempty"`
Level string `koanf:"level" json:"level,omitempty"`
Pretty bool `koanf:"pretty" json:"pretty,omitempty"`
ComponentLevels map[string]string `koanf:"component_levels" json:"component_levels,omitempty"`
}

func (l Logging) validate() []error {
Expand Down
6 changes: 3 additions & 3 deletions server/internal/election/candidate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sync/atomic"
"time"

"github.com/pgEdge/control-plane/server/internal/logging"
"github.com/pgEdge/control-plane/server/internal/storage"
"github.com/rs/zerolog"
)
Expand Down Expand Up @@ -42,16 +43,15 @@ type Candidate struct {
// leadership.
func NewCandidate(
store *ElectionStore,
logger zerolog.Logger,
loggerFactory *logging.Factory,
electionName Name,
candidateID string,
ttl time.Duration,
onClaim []ClaimHandler,
) *Candidate {
return &Candidate{
store: store,
logger: logger.With().
Str("component", "election_candidate").
logger: loggerFactory.Logger("election_candidate").With().
Stringer("election_name", electionName).
Str("candidate_id", candidateID).
Logger(),
Expand Down
4 changes: 2 additions & 2 deletions server/internal/election/candidate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (
func TestCandidate(t *testing.T) {
server := storagetest.NewEtcdTestServer(t)
client := server.Client(t)
logger := testutils.Logger(t)
loggerFactory := testutils.LoggerFactory(t)
store := election.NewElectionStore(client, uuid.NewString())
electionSvc := election.NewService(store, logger)
electionSvc := election.NewService(store, loggerFactory)

t.Run("basic functionality", func(t *testing.T) {
ctx := t.Context()
Expand Down
9 changes: 5 additions & 4 deletions server/internal/election/provide.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package election

import (
"github.com/pgEdge/control-plane/server/internal/config"
"github.com/rs/zerolog"
"github.com/samber/do"
clientv3 "go.etcd.io/etcd/client/v3"

"github.com/pgEdge/control-plane/server/internal/config"
"github.com/pgEdge/control-plane/server/internal/logging"
)

func Provide(i *do.Injector) {
Expand Down Expand Up @@ -32,10 +33,10 @@ func provideService(i *do.Injector) {
if err != nil {
return nil, err
}
logger, err := do.Invoke[zerolog.Logger](i)
loggerFactory, err := do.Invoke[*logging.Factory](i)
if err != nil {
return nil, err
}
return NewService(store, logger), nil
return NewService(store, loggerFactory), nil
})
}
14 changes: 7 additions & 7 deletions server/internal/election/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ package election
import (
"time"

"github.com/rs/zerolog"
"github.com/pgEdge/control-plane/server/internal/logging"
)

// Service manages election operations.
type Service struct {
store *ElectionStore
logger zerolog.Logger
store *ElectionStore
loggerFactory *logging.Factory
}

// NewService returns a new Service.
func NewService(
store *ElectionStore,
logger zerolog.Logger,
loggerFactory *logging.Factory,
) *Service {
return &Service{
store: store,
logger: logger,
store: store,
loggerFactory: loggerFactory,
}
}

// NewCandidate creates a new Candidate for the given election. candidateID must
// be unique amongst candidates.
func (s *Service) NewCandidate(electionName Name, candidateID string, ttl time.Duration, onClaim ...ClaimHandler) *Candidate {
return NewCandidate(s.store, s.logger, electionName, candidateID, ttl, onClaim)
return NewCandidate(s.store, s.loggerFactory, electionName, candidateID, ttl, onClaim)
}
29 changes: 15 additions & 14 deletions server/internal/etcd/embedded.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/pgEdge/control-plane/server/internal/certificates"
"github.com/pgEdge/control-plane/server/internal/config"
"github.com/pgEdge/control-plane/server/internal/healthcheck"
"github.com/pgEdge/control-plane/server/internal/logging"
"github.com/pgEdge/control-plane/server/internal/utils"
)

Expand All @@ -32,22 +33,22 @@ var _ do.Shutdownable = (*EmbeddedEtcd)(nil)
const quotaBackendBytes = 8 * 1024 * 1024 * 1024 // 8GB

type EmbeddedEtcd struct {
mu sync.Mutex
certSvc *certificates.Service
client *clientv3.Client
etcd *embed.Etcd
logger zerolog.Logger
cfg *config.Manager
initialized chan struct{}
mu sync.Mutex
certSvc *certificates.Service
client *clientv3.Client
etcd *embed.Etcd
logger zerolog.Logger
loggerFactory *logging.Factory
cfg *config.Manager
initialized chan struct{}
}

func NewEmbeddedEtcd(cfg *config.Manager, logger zerolog.Logger) *EmbeddedEtcd {
func NewEmbeddedEtcd(cfg *config.Manager, loggerFactory *logging.Factory) *EmbeddedEtcd {
return &EmbeddedEtcd{
cfg: cfg,
initialized: make(chan struct{}),
logger: logger.With().
Str("component", "etcd_server").
Logger(),
cfg: cfg,
initialized: make(chan struct{}),
logger: loggerFactory.Logger("embedded_etcd"),
loggerFactory: loggerFactory,
}
}

Expand Down Expand Up @@ -522,7 +523,7 @@ func (e *EmbeddedEtcd) ChangeMode(ctx context.Context, mode config.EtcdMode) (Et
return nil, err
}

remote := NewRemoteEtcd(e.cfg, e.logger)
remote := NewRemoteEtcd(e.cfg, e.loggerFactory)
if err := remote.Start(ctx); err != nil {
return nil, fmt.Errorf("failed to start remote client: %w", err)
}
Expand Down
16 changes: 8 additions & 8 deletions server/internal/etcd/embedded_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestEmbeddedEtcd(t *testing.T) {
},
}

server := etcd.NewEmbeddedEtcd(cfgMgr(t, cfg), testutils.Logger(t))
server := etcd.NewEmbeddedEtcd(cfgMgr(t, cfg), testutils.LoggerFactory(t))
require.NotNil(t, server)

initialized, err := server.IsInitialized()
Expand Down Expand Up @@ -101,7 +101,7 @@ func TestEmbeddedEtcd(t *testing.T) {
},
}

serverA := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgA), testutils.Logger(t))
serverA := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgA), testutils.LoggerFactory(t))
require.NotNil(t, serverA)

err := serverA.Start(ctx)
Expand Down Expand Up @@ -130,7 +130,7 @@ func TestEmbeddedEtcd(t *testing.T) {
},
}

serverB := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgB), testutils.Logger(t))
serverB := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgB), testutils.LoggerFactory(t))
require.NotNil(t, serverB)

// Generate credentials for server B
Expand Down Expand Up @@ -209,7 +209,7 @@ func TestEmbeddedEtcd(t *testing.T) {
})

t.Run("three member cluster", func(t *testing.T) {
logger := testutils.Logger(t)
loggerFactory := testutils.LoggerFactory(t)
ctx := context.Background()

// Initialize the cluster
Expand All @@ -224,7 +224,7 @@ func TestEmbeddedEtcd(t *testing.T) {
PeerPort: storagetest.GetFreePort(t),
},
}
serverA := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgA), logger)
serverA := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgA), loggerFactory)
require.NoError(t, serverA.Start(ctx))
t.Cleanup(func() {
serverA.Shutdown()
Expand All @@ -241,7 +241,7 @@ func TestEmbeddedEtcd(t *testing.T) {
PeerPort: storagetest.GetFreePort(t),
},
}
serverB := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgB), logger)
serverB := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgB), loggerFactory)

cfgC := config.Config{
HostID: uuid.NewString(),
Expand All @@ -254,7 +254,7 @@ func TestEmbeddedEtcd(t *testing.T) {
PeerPort: storagetest.GetFreePort(t),
},
}
serverC := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgC), logger)
serverC := etcd.NewEmbeddedEtcd(cfgMgr(t, cfgC), loggerFactory)

leader, err := serverA.Leader(ctx)
require.NoError(t, err)
Expand Down Expand Up @@ -387,7 +387,7 @@ func TestEmbeddedEtcd(t *testing.T) {
},
}

server := etcd.NewEmbeddedEtcd(cfgMgr(t, cfg), testutils.Logger(t))
server := etcd.NewEmbeddedEtcd(cfgMgr(t, cfg), testutils.LoggerFactory(t))
require.NotNil(t, server)

err := server.Start(ctx)
Expand Down
17 changes: 11 additions & 6 deletions server/internal/etcd/provide.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"google.golang.org/grpc/grpclog"

"github.com/pgEdge/control-plane/server/internal/config"
"github.com/pgEdge/control-plane/server/internal/logging"
)

func Provide(i *do.Injector) {
Expand All @@ -30,12 +31,12 @@ func provideClient(i *do.Injector) {
}

// newEtcdForMode creates an Etcd instance based on the specified mode.
func newEtcdForMode(mode config.EtcdMode, cfg *config.Manager, logger zerolog.Logger) (Etcd, error) {
func newEtcdForMode(mode config.EtcdMode, cfg *config.Manager, loggerFactory *logging.Factory) (Etcd, error) {
switch mode {
case config.EtcdModeServer:
return NewEmbeddedEtcd(cfg, logger), nil
return NewEmbeddedEtcd(cfg, loggerFactory), nil
case config.EtcdModeClient:
return NewRemoteEtcd(cfg, logger), nil
return NewRemoteEtcd(cfg, loggerFactory), nil
default:
return nil, fmt.Errorf("invalid etcd mode: %s", mode)
}
Expand All @@ -51,6 +52,10 @@ func provideEtcd(i *do.Injector) {
if err != nil {
return nil, err
}
loggerFactory, err := do.Invoke[*logging.Factory](i)
if err != nil {
return nil, err
}

appCfg := cfg.Config()
generated := cfg.GeneratedConfig()
Expand All @@ -71,7 +76,7 @@ func provideEtcd(i *do.Injector) {

switch {
case oldMode == "" || oldMode == newMode:
etcd, err := newEtcdForMode(newMode, cfg, logger)
etcd, err := newEtcdForMode(newMode, cfg, loggerFactory)
if err != nil {
return nil, err
}
Expand All @@ -90,10 +95,10 @@ func provideEtcd(i *do.Injector) {

return etcd, nil
case oldMode == config.EtcdModeServer && newMode == config.EtcdModeClient:
embedded := NewEmbeddedEtcd(cfg, logger)
embedded := NewEmbeddedEtcd(cfg, loggerFactory)
return embedded.ChangeMode(ctx, newMode)
case oldMode == config.EtcdModeClient && newMode == config.EtcdModeServer:
remote := NewRemoteEtcd(cfg, logger)
remote := NewRemoteEtcd(cfg, loggerFactory)
return remote.ChangeMode(ctx, newMode)
default:
return nil, fmt.Errorf("unsupported etcd mode transition: %s -> %s", oldMode, newMode)
Expand Down
Loading