From 542aa10cd10e4c6febb47fdff6abe64d07ce7194 Mon Sep 17 00:00:00 2001 From: Michael MacDonald Date: Tue, 23 Jan 2024 12:48:56 -0500 Subject: [PATCH] DAOS-14850 control: Allow logging.Logger in Context (#13569) Updates control plane tools to set a context in a logger for ease of debug/trace logging. Signed-off-by: Michael MacDonald --- src/control/cmd/daos_agent/attachinfo.go | 4 +- src/control/cmd/daos_agent/network.go | 3 +- src/control/cmd/daos_agent/start.go | 2 +- src/control/cmd/daos_server/auto.go | 2 +- src/control/cmd/daos_server/network.go | 2 +- src/control/cmd/dmg/auto.go | 2 +- src/control/cmd/dmg/cont.go | 4 +- src/control/cmd/dmg/firmware.go | 5 +- src/control/cmd/dmg/network.go | 3 +- src/control/cmd/dmg/pool.go | 34 ++++++------ src/control/cmd/dmg/server.go | 3 +- src/control/cmd/dmg/storage.go | 9 ++-- src/control/cmd/dmg/storage_query.go | 16 +++--- src/control/cmd/dmg/system.go | 25 +++++---- src/control/cmd/dmg/telemetry.go | 5 +- src/control/common/cmdutil/logging.go | 17 ++++++ src/control/logging/context.go | 52 +++++++++++++++++++ src/control/logging/context_test.go | 66 ++++++++++++++++++++++++ 18 files changed, 190 insertions(+), 64 deletions(-) create mode 100644 src/control/logging/context.go create mode 100644 src/control/logging/context_test.go diff --git a/src/control/cmd/daos_agent/attachinfo.go b/src/control/cmd/daos_agent/attachinfo.go index 76e42e53974..4f65605656d 100644 --- a/src/control/cmd/daos_agent/attachinfo.go +++ b/src/control/cmd/daos_agent/attachinfo.go @@ -7,7 +7,6 @@ package main import ( - "context" "fmt" "os" @@ -21,6 +20,7 @@ import ( type dumpAttachInfoCmd struct { configCmd ctlInvokerCmd + cmdutil.LogCmd cmdutil.JSONOutputCmd Output string `short:"o" long:"output" default:"stdout" description:"Dump output to this location"` } @@ -36,7 +36,7 @@ func (cmd *dumpAttachInfoCmd) Execute(_ []string) error { out = f } - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.GetAttachInfoReq{ AllRanks: true, } diff --git a/src/control/cmd/daos_agent/network.go b/src/control/cmd/daos_agent/network.go index 42c3407ca49..28215a9c319 100644 --- a/src/control/cmd/daos_agent/network.go +++ b/src/control/cmd/daos_agent/network.go @@ -7,7 +7,6 @@ package main import ( - "context" "strings" "github.com/daos-stack/daos/src/control/cmd/dmg/pretty" @@ -32,7 +31,7 @@ func (cmd *netScanCmd) Execute(_ []string) error { fabricScanner := hwprov.DefaultFabricScanner(cmd.Logger) - results, err := fabricScanner.Scan(context.Background(), prov) + results, err := fabricScanner.Scan(cmd.MustLogCtx(), prov) if err != nil { return nil } diff --git a/src/control/cmd/daos_agent/start.go b/src/control/cmd/daos_agent/start.go index 791af47ba63..cb5505234d5 100644 --- a/src/control/cmd/daos_agent/start.go +++ b/src/control/cmd/daos_agent/start.go @@ -54,7 +54,7 @@ func (cmd *startCmd) Execute(_ []string) error { cmd.Infof("Starting %s (pid %d)", versionString(), os.Getpid()) startedAt := time.Now() - parent, shutdown := context.WithCancel(context.Background()) + parent, shutdown := context.WithCancel(cmd.MustLogCtx()) defer shutdown() var shuttingDown atm.Bool diff --git a/src/control/cmd/daos_server/auto.go b/src/control/cmd/daos_server/auto.go index d4ccc1c2ec1..93a3fd83626 100644 --- a/src/control/cmd/daos_server/auto.go +++ b/src/control/cmd/daos_server/auto.go @@ -192,5 +192,5 @@ func (cmd *configGenCmd) Execute(_ []string) error { return err } - return cmd.confGenPrint(context.Background(), getLocalFabric, getLocalStorage) + return cmd.confGenPrint(cmd.MustLogCtx(), getLocalFabric, getLocalStorage) } diff --git a/src/control/cmd/daos_server/network.go b/src/control/cmd/daos_server/network.go index d619cbc7457..a0b80cb7ae8 100644 --- a/src/control/cmd/daos_server/network.go +++ b/src/control/cmd/daos_server/network.go @@ -83,7 +83,7 @@ func (cmd *networkScanCmd) Execute(_ []string) error { return err } - ctx := context.Background() + ctx := cmd.MustLogCtx() fs := hwprov.DefaultFabricScanner(cmd.Logger) var prov string diff --git a/src/control/cmd/dmg/auto.go b/src/control/cmd/dmg/auto.go index a85638c14d0..3e97a528cc8 100644 --- a/src/control/cmd/dmg/auto.go +++ b/src/control/cmd/dmg/auto.go @@ -126,5 +126,5 @@ func (cmd *configGenCmd) confGenPrint(ctx context.Context) error { // parameters suitable to be used across all hosts in provided host list. Use the control API to // generate config from remote scan results. func (cmd *configGenCmd) Execute(_ []string) error { - return cmd.confGenPrint(context.Background()) + return cmd.confGenPrint(cmd.MustLogCtx()) } diff --git a/src/control/cmd/dmg/cont.go b/src/control/cmd/dmg/cont.go index 5ad087b0676..8906773bd1a 100644 --- a/src/control/cmd/dmg/cont.go +++ b/src/control/cmd/dmg/cont.go @@ -7,8 +7,6 @@ package main import ( - "context" - "github.com/jessevdk/go-flags" "github.com/pkg/errors" @@ -49,7 +47,7 @@ func (c *ContSetOwnerCmd) Execute(args []string) error { Group: c.GroupName.String(), } - ctx := context.Background() + ctx := c.MustLogCtx() err := control.ContSetOwner(ctx, c.ctlInvoker, req) if err != nil { msg = errors.WithMessage(err, "FAILED").Error() diff --git a/src/control/cmd/dmg/firmware.go b/src/control/cmd/dmg/firmware.go index 16748d37b32..4154a980b8d 100644 --- a/src/control/cmd/dmg/firmware.go +++ b/src/control/cmd/dmg/firmware.go @@ -7,7 +7,6 @@ package main import ( - "context" "io" "strings" @@ -42,7 +41,7 @@ type firmwareQueryCmd struct { // Execute runs the firmware query command. func (cmd *firmwareQueryCmd) Execute(args []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.FirmwareQueryReq{ SCM: cmd.isSCMRequested(), @@ -127,7 +126,7 @@ type firmwareUpdateCmd struct { // Execute runs the firmware update command. func (cmd *firmwareUpdateCmd) Execute(args []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.FirmwareUpdateReq{ FirmwarePath: cmd.FilePath, diff --git a/src/control/cmd/dmg/network.go b/src/control/cmd/dmg/network.go index e55ddadb635..8ccd25a7a53 100644 --- a/src/control/cmd/dmg/network.go +++ b/src/control/cmd/dmg/network.go @@ -7,7 +7,6 @@ package main import ( - "context" "strings" "github.com/daos-stack/daos/src/control/cmd/dmg/pretty" @@ -32,7 +31,7 @@ type networkScanCmd struct { } func (cmd *networkScanCmd) Execute(_ []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.NetworkScanReq{ Provider: cmd.FabricProvider, } diff --git a/src/control/cmd/dmg/pool.go b/src/control/cmd/dmg/pool.go index 5f8d29a9a8e..099348d4b8e 100644 --- a/src/control/cmd/dmg/pool.go +++ b/src/control/cmd/dmg/pool.go @@ -255,7 +255,7 @@ func (cmd *PoolCreateCmd) Execute(args []string) error { // TODO (DAOS-9556) Update the protocol with a new message allowing to perform the // queries of storage request and the pool creation from the management server scmBytes, nvmeBytes, err := control.GetMaxPoolSize( - context.Background(), + cmd.MustLogCtx(), cmd.Logger, cmd.ctlInvoker, ranklist.RankList(req.Ranks)) @@ -375,7 +375,7 @@ func (cmd *PoolListCmd) Execute(_ []string) (errOut error) { NoQuery: cmd.NoQuery, } - resp, err := control.ListPools(context.Background(), cmd.ctlInvoker, req) + resp, err := control.ListPools(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return err // control api returned an error, disregard response } @@ -435,7 +435,7 @@ func (cmd *PoolDestroyCmd) Execute(args []string) error { Recursive: cmd.Recursive, } - err := control.PoolDestroy(context.Background(), cmd.ctlInvoker, req) + err := control.PoolDestroy(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { msg = errors.WithMessage(err, "failed").Error() } @@ -457,7 +457,7 @@ func (cmd *PoolEvictCmd) Execute(args []string) error { req := &control.PoolEvictReq{ID: cmd.PoolID().String()} - err := control.PoolEvict(context.Background(), cmd.ctlInvoker, req) + err := control.PoolEvict(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { msg = errors.WithMessage(err, "failed").Error() } @@ -485,7 +485,7 @@ func (cmd *PoolExcludeCmd) Execute(args []string) error { req := &control.PoolExcludeReq{ID: cmd.PoolID().String(), Rank: ranklist.Rank(cmd.Rank), Targetidx: idxlist} - err := control.PoolExclude(context.Background(), cmd.ctlInvoker, req) + err := control.PoolExclude(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { msg = errors.WithMessage(err, "failed").Error() } @@ -514,7 +514,7 @@ func (cmd *PoolDrainCmd) Execute(args []string) error { req := &control.PoolDrainReq{ID: cmd.PoolID().String(), Rank: ranklist.Rank(cmd.Rank), Targetidx: idxlist} - err := control.PoolDrain(context.Background(), cmd.ctlInvoker, req) + err := control.PoolDrain(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { msg = errors.WithMessage(err, "failed").Error() } @@ -539,7 +539,7 @@ func (cmd *PoolExtendCmd) Execute(args []string) error { Ranks: cmd.RankList.Ranks(), } - err := control.PoolExtend(context.Background(), cmd.ctlInvoker, req) + err := control.PoolExtend(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { msg = errors.WithMessage(err, "failed").Error() } @@ -572,7 +572,7 @@ func (cmd *PoolReintegrateCmd) Execute(args []string) error { Targetidx: idxlist, } - err := control.PoolReintegrate(context.Background(), cmd.ctlInvoker, req) + err := control.PoolReintegrate(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { msg = errors.WithMessage(err, "failed").Error() } @@ -602,7 +602,7 @@ func (cmd *PoolQueryCmd) Execute(args []string) error { req.IncludeEnabledRanks = cmd.ShowEnabledRanks req.IncludeDisabledRanks = cmd.ShowDisabledRanks - resp, err := control.PoolQuery(context.Background(), cmd.ctlInvoker, req) + resp, err := control.PoolQuery(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) @@ -642,7 +642,7 @@ func (cmd *PoolQueryTargetsCmd) Execute(args []string) error { Targets: tgtsList, } - resp, err := control.PoolQueryTargets(context.Background(), cmd.ctlInvoker, req) + resp, err := control.PoolQueryTargets(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) @@ -671,7 +671,7 @@ func (cmd *PoolUpgradeCmd) Execute(args []string) error { ID: cmd.PoolID().String(), } - err := control.PoolUpgrade(context.Background(), cmd.ctlInvoker, req) + err := control.PoolUpgrade(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return errors.Wrap(err, "pool upgrade failed") } @@ -708,7 +708,7 @@ func (cmd *PoolSetPropCmd) Execute(_ []string) error { Properties: cmd.Args.Props.ToSet, } - err := control.PoolSetProp(context.Background(), cmd.ctlInvoker, req) + err := control.PoolSetProp(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(nil, err) } @@ -736,7 +736,7 @@ func (cmd *PoolGetPropCmd) Execute(_ []string) error { Properties: cmd.Args.Props.ToGet, } - resp, err := control.PoolGetProp(context.Background(), cmd.ctlInvoker, req) + resp, err := control.PoolGetProp(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) } @@ -765,7 +765,7 @@ type PoolGetACLCmd struct { func (cmd *PoolGetACLCmd) Execute(args []string) error { req := &control.PoolGetACLReq{ID: cmd.PoolID().String()} - resp, err := control.PoolGetACL(context.Background(), cmd.ctlInvoker, req) + resp, err := control.PoolGetACL(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) } @@ -835,7 +835,7 @@ func (cmd *PoolOverwriteACLCmd) Execute(args []string) error { ACL: acl, } - resp, err := control.PoolOverwriteACL(context.Background(), cmd.ctlInvoker, req) + resp, err := control.PoolOverwriteACL(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) } @@ -883,7 +883,7 @@ func (cmd *PoolUpdateACLCmd) Execute(args []string) error { ACL: acl, } - resp, err := control.PoolUpdateACL(context.Background(), cmd.ctlInvoker, req) + resp, err := control.PoolUpdateACL(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) } @@ -913,7 +913,7 @@ func (cmd *PoolDeleteACLCmd) Execute(args []string) error { Principal: cmd.Principal, } - resp, err := control.PoolDeleteACL(context.Background(), cmd.ctlInvoker, req) + resp, err := control.PoolDeleteACL(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) } diff --git a/src/control/cmd/dmg/server.go b/src/control/cmd/dmg/server.go index aa4a6e91f22..7f61b6e165b 100644 --- a/src/control/cmd/dmg/server.go +++ b/src/control/cmd/dmg/server.go @@ -7,7 +7,6 @@ package main import ( - "context" "strings" "github.com/pkg/errors" @@ -49,7 +48,7 @@ func (cmd *serverSetLogMasksCmd) Execute(_ []string) (errOut error) { cmd.Debugf("set log masks request: %+v", req) - resp, err := control.SetEngineLogMasks(context.Background(), cmd.ctlInvoker, req) + resp, err := control.SetEngineLogMasks(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return err // control api returned an error, disregard response } diff --git a/src/control/cmd/dmg/storage.go b/src/control/cmd/dmg/storage.go index fea3160f74c..ae0d15ac187 100644 --- a/src/control/cmd/dmg/storage.go +++ b/src/control/cmd/dmg/storage.go @@ -7,7 +7,6 @@ package main import ( - "context" "strings" "github.com/pkg/errors" @@ -61,7 +60,7 @@ func (cmd *storageScanCmd) Execute(_ []string) error { cmd.Debugf("storage scan request: %+v", req) - resp, err := control.StorageScan(context.Background(), cmd.ctlInvoker, req) + resp, err := control.StorageScan(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return err } @@ -115,7 +114,7 @@ type storageFormatCmd struct { // // Run NVMe and SCM storage format on all connected servers. func (cmd *storageFormatCmd) Execute(args []string) (err error) { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.StorageFormatReq{Reformat: cmd.Force} req.SetHostList(cmd.getHostList()) @@ -164,7 +163,7 @@ type nvmeRebindCmd struct { // // Rebind NVMe SSD from kernel driver and bind to user-space driver on single server. func (cmd *nvmeRebindCmd) Execute(args []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() if len(cmd.getHostList()) != 1 { return errors.New("command expects a single host in hostlist") @@ -213,7 +212,7 @@ type nvmeAddDeviceCmd struct { // // Add recently inserted NVMe SSD to a running engine by updating relevant NVMe config file. func (cmd *nvmeAddDeviceCmd) Execute(args []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() if len(cmd.getHostList()) != 1 { return errors.New("command expects a single host in hostlist") diff --git a/src/control/cmd/dmg/storage_query.go b/src/control/cmd/dmg/storage_query.go index e5c9432b1e4..c05a2437e87 100644 --- a/src/control/cmd/dmg/storage_query.go +++ b/src/control/cmd/dmg/storage_query.go @@ -75,7 +75,7 @@ type devHealthQueryCmd struct { } func (cmd *devHealthQueryCmd) Execute(_ []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.SmdQueryReq{ OmitPools: true, IncludeBioHealth: true, @@ -94,7 +94,7 @@ type listDevicesQueryCmd struct { } func (cmd *listDevicesQueryCmd) Execute(_ []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.SmdQueryReq{ OmitPools: true, @@ -114,7 +114,7 @@ type listPoolsQueryCmd struct { } func (cmd *listPoolsQueryCmd) Execute(_ []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.SmdQueryReq{ OmitDevices: true, Rank: cmd.GetRank(), @@ -135,7 +135,7 @@ type usageQueryCmd struct { // // Queries NVMe and SCM usage on hosts. func (cmd *usageQueryCmd) Execute(_ []string) error { - ctx := context.Background() + ctx := cmd.MustLogCtx() req := &control.StorageScanReq{Usage: true} req.SetHostList(cmd.getHostList()) resp, err := control.StorageScan(ctx, cmd.ctlInvoker, req) @@ -217,7 +217,7 @@ func (cmd *nvmeSetFaultyCmd) Execute(_ []string) error { Operation: control.SetFaultyOp, IDs: cmd.UUID, } - return cmd.makeRequest(context.Background(), req) + return cmd.makeRequest(cmd.MustLogCtx(), req) } // storageReplaceCmd is the struct representing the replace storage subcommand @@ -251,7 +251,7 @@ func (cmd *nvmeReplaceCmd) Execute(_ []string) error { ReplaceUUID: cmd.NewDevUUID, ReplaceNoReint: cmd.NoReint, } - return cmd.makeRequest(context.Background(), req) + return cmd.makeRequest(cmd.MustLogCtx(), req) } type ledCmd struct { @@ -291,7 +291,7 @@ func (cmd *ledIdentifyCmd) Execute(_ []string) error { } req.Operation = control.LedResetOp } - return cmd.makeRequest(context.Background(), req, pretty.PrintOnlyLEDInfo()) + return cmd.makeRequest(cmd.MustLogCtx(), req, pretty.PrintOnlyLEDInfo()) } type ledCheckCmd struct { @@ -309,5 +309,5 @@ func (cmd *ledCheckCmd) Execute(_ []string) error { Operation: control.LedCheckOp, IDs: cmd.Args.IDs, } - return cmd.makeRequest(context.Background(), req, pretty.PrintOnlyLEDInfo()) + return cmd.makeRequest(cmd.MustLogCtx(), req, pretty.PrintOnlyLEDInfo()) } diff --git a/src/control/cmd/dmg/system.go b/src/control/cmd/dmg/system.go index 58834554081..f67eb6a80b0 100644 --- a/src/control/cmd/dmg/system.go +++ b/src/control/cmd/dmg/system.go @@ -7,7 +7,6 @@ package main import ( - "context" "fmt" "io" "strings" @@ -58,7 +57,7 @@ func (cmd *leaderQueryCmd) Execute(_ []string) (errOut error) { return errors.New("no configuration loaded") } - ctx := context.Background() + ctx := cmd.MustLogCtx() req := new(control.LeaderQueryReq) resp, err := control.LeaderQuery(ctx, cmd.ctlInvoker, req) @@ -117,7 +116,7 @@ func (cmd *systemQueryCmd) Execute(_ []string) (errOut error) { req.Hosts.Replace(&cmd.Hosts.HostSet) req.Ranks.Replace(&cmd.Ranks.RankSet) - resp, err := control.SystemQuery(context.Background(), cmd.ctlInvoker, req) + resp, err := control.SystemQuery(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return err // control api returned an error, disregard response } @@ -145,7 +144,7 @@ type systemEraseCmd struct { } func (cmd *systemEraseCmd) Execute(_ []string) error { - resp, err := control.SystemErase(context.Background(), cmd.ctlInvoker, new(control.SystemEraseReq)) + resp, err := control.SystemErase(cmd.MustLogCtx(), cmd.ctlInvoker, new(control.SystemEraseReq)) if err != nil { return err } @@ -178,7 +177,7 @@ func (cmd *systemStopCmd) Execute(_ []string) (errOut error) { req.Hosts.Replace(&cmd.Hosts.HostSet) req.Ranks.Replace(&cmd.Ranks.RankSet) - resp, err := control.SystemStop(context.Background(), cmd.ctlInvoker, req) + resp, err := control.SystemStop(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return err // control api returned an error, disregard response } @@ -219,7 +218,7 @@ func (cmd *baseExcludeCmd) execute(clear bool) error { req.Hosts.Replace(&cmd.Hosts.HostSet) req.Ranks.Replace(&cmd.Ranks.RankSet) - resp, err := control.SystemExclude(context.Background(), cmd.ctlInvoker, req) + resp, err := control.SystemExclude(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return err // control api returned an error, disregard response } @@ -279,7 +278,7 @@ func (cmd *systemStartCmd) Execute(_ []string) (errOut error) { req.Hosts.Replace(&cmd.Hosts.HostSet) req.Ranks.Replace(&cmd.Ranks.RankSet) - resp, err := control.SystemStart(context.Background(), cmd.ctlInvoker, req) + resp, err := control.SystemStart(cmd.MustLogCtx(), cmd.ctlInvoker, req) if err != nil { return err // control api returned an error, disregard response } @@ -318,7 +317,7 @@ func (cmd *systemCleanupCmd) Execute(_ []string) (errOut error) { errOut = errors.Wrap(errOut, "system cleanup failed") }() - ctx := context.Background() + ctx := cmd.MustLogCtx() req := new(control.SystemCleanupReq) req.SetSystem(cmd.config.SystemName) req.Machine = cmd.Args.Machine @@ -365,7 +364,7 @@ func (cmd *systemSetAttrCmd) Execute(_ []string) error { Attributes: cmd.Args.Attrs.ParsedProps, } - err := control.SystemSetAttr(context.Background(), cmd.ctlInvoker, req) + err := control.SystemSetAttr(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(nil, err) } @@ -417,7 +416,7 @@ func (cmd *systemGetAttrCmd) Execute(_ []string) error { Keys: cmd.Args.Attrs.ParsedProps.ToSlice(), } - resp, err := control.SystemGetAttr(context.Background(), cmd.ctlInvoker, req) + resp, err := control.SystemGetAttr(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp, err) } @@ -454,7 +453,7 @@ func (cmd *systemDelAttrCmd) Execute(_ []string) error { req.Attributes[key] = "" } - err := control.SystemSetAttr(context.Background(), cmd.ctlInvoker, req) + err := control.SystemSetAttr(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(nil, err) } @@ -530,7 +529,7 @@ func (cmd *systemSetPropCmd) Execute(_ []string) error { Properties: cmd.Args.Props.ParsedProps, } - err := control.SystemSetProp(context.Background(), cmd.ctlInvoker, req) + err := control.SystemSetProp(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(nil, err) } @@ -623,7 +622,7 @@ func (cmd *systemGetPropCmd) Execute(_ []string) error { Keys: cmd.Args.Props.ParsedProps, } - resp, err := control.SystemGetProp(context.Background(), cmd.ctlInvoker, req) + resp, err := control.SystemGetProp(cmd.MustLogCtx(), cmd.ctlInvoker, req) if cmd.JSONOutputEnabled() { return cmd.OutputJSON(resp.Properties, err) } diff --git a/src/control/cmd/dmg/telemetry.go b/src/control/cmd/dmg/telemetry.go index 9351496adde..fd63164b438 100644 --- a/src/control/cmd/dmg/telemetry.go +++ b/src/control/cmd/dmg/telemetry.go @@ -9,7 +9,6 @@ package main import ( "archive/tar" "compress/gzip" - "context" "encoding/json" "fmt" "io" @@ -324,7 +323,7 @@ func (cmd *metricsListCmd) Execute(args []string) error { cmd.Info(getConnectingMsg(req.Host, req.Port)) } - resp, err := control.MetricsList(context.Background(), req) + resp, err := control.MetricsList(cmd.MustLogCtx(), req) if err != nil { return err } @@ -380,7 +379,7 @@ func (cmd *metricsQueryCmd) Execute(args []string) error { cmd.Info(getConnectingMsg(req.Host, req.Port)) } - resp, err := control.MetricsQuery(context.Background(), req) + resp, err := control.MetricsQuery(cmd.MustLogCtx(), req) if err != nil { return err } diff --git a/src/control/common/cmdutil/logging.go b/src/control/common/cmdutil/logging.go index 8b814eb2163..5c713d5dca7 100644 --- a/src/control/common/cmdutil/logging.go +++ b/src/control/common/cmdutil/logging.go @@ -7,6 +7,8 @@ package cmdutil import ( + "context" + "github.com/daos-stack/daos/src/control/logging" ) @@ -30,3 +32,18 @@ type ( func (cmd *LogCmd) SetLog(log logging.Logger) { cmd.Logger = log } + +// LogCtx returns a context with the command's logger set. +func (cmd *LogCmd) LogCtx() (context.Context, error) { + return logging.ToContext(context.Background(), cmd.Logger) +} + +// MustLogCtx returns a context with the command's logger set. +// NB: Panics on error. +func (cmd *LogCmd) MustLogCtx() context.Context { + ctx, err := cmd.LogCtx() + if err != nil { + panic(err) + } + return ctx +} diff --git a/src/control/logging/context.go b/src/control/logging/context.go new file mode 100644 index 00000000000..f3250fd562b --- /dev/null +++ b/src/control/logging/context.go @@ -0,0 +1,52 @@ +// +// (C) Copyright 2024 Intel Corporation. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package logging + +import ( + "context" + "errors" +) + +type contextKeyType string + +var contextKey contextKeyType = "logging.Logger" + +func getCtxLogger(ctx context.Context) (Logger, bool) { + if ctx == nil { + return nil, false + } + + if logger, ok := ctx.Value(contextKey).(Logger); ok { + return logger, true + } + return nil, false +} + +// FromContext returns the logger from the context, +// or a no-op logger if no logger is present. +func FromContext(ctx context.Context) Logger { + if logger, ok := getCtxLogger(ctx); ok { + return logger + } + return &LeveledLogger{level: LogLevelDisabled} +} + +// ToContext adds the logger to the context if +// it is not already present. +func ToContext(ctx context.Context, logger Logger) (context.Context, error) { + if ctx == nil { + return nil, errors.New("nil context") + } + if logger == nil { + return nil, errors.New("nil logger") + } + + if _, ok := getCtxLogger(ctx); ok { + return nil, errors.New("logger already present in context") + } + return context.WithValue(ctx, contextKey, logger), nil +} diff --git a/src/control/logging/context_test.go b/src/control/logging/context_test.go new file mode 100644 index 00000000000..8b798264072 --- /dev/null +++ b/src/control/logging/context_test.go @@ -0,0 +1,66 @@ +// +// (C) Copyright 2024 Intel Corporation. +// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// + +package logging_test + +import ( + "strings" + "testing" + + "github.com/daos-stack/daos/src/control/common/test" + "github.com/daos-stack/daos/src/control/logging" +) + +func TestLogging_ToFromContext(t *testing.T) { + log, buf := logging.NewTestLogger(t.Name()) + defer test.ShowBufferOnFailure(t, buf) + + ctx, err := logging.ToContext(test.Context(t), log) + if err != nil { + t.Fatal(err) + } + log2 := logging.FromContext(ctx) + log2.Info("test") + + if !strings.Contains(buf.String(), "test") { + t.Fatal("expected test message in log buffer") + } +} + +func TestLogging_FromContext_Unset(t *testing.T) { + log := logging.FromContext(test.Context(t)) + log.Info("shouldn't panic (noop)") +} + +func TestLogging_FromContext_NilCtx(t *testing.T) { + log := logging.FromContext(nil) + log.Info("shouldn't panic (noop)") +} + +func TestLogging_ToContext_NilCtx(t *testing.T) { + _, err := logging.ToContext(nil, &logging.LeveledLogger{}) + if err == nil { + t.Fatal("expected error") + } +} + +func TestLogging_ToContext_NilLogger(t *testing.T) { + _, err := logging.ToContext(test.Context(t), nil) + if err == nil { + t.Fatal("expected error") + } +} + +func TestLogging_ToContext_AlreadySet(t *testing.T) { + ctx, err := logging.ToContext(test.Context(t), &logging.LeveledLogger{}) + if err != nil { + t.Fatal(err) + } + _, err = logging.ToContext(ctx, &logging.LeveledLogger{}) + if err == nil { + t.Fatal("expected error") + } +}