Add node addresses as debug information #147

Merged
fyrchik merged 2 commits from ironbee/frostfs-sdk-go:extend_debug_info into master 2024-09-04 19:51:15 +00:00
2 changed files with 80 additions and 14 deletions

View file

@ -2150,7 +2150,7 @@ func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (oid.ID, error)
if err != nil {
// removes session token from cache in case of token error
p.checkSessionTokenErr(err, ctxCall.endpoint)
return id, fmt.Errorf("init writing on API client: %w", err)
return id, fmt.Errorf("init writing on API client %s: %w", ctxCall.endpoint, err)
dkirillov marked this conversation as resolved Outdated

Why don't use ctxCall.endpoint?

Why don't use `ctxCall.endpoint`?
}
return id, nil
@ -2193,7 +2193,7 @@ func (p *Pool) DeleteObject(ctx context.Context, prm PrmObjectDelete) error {
return p.call(ctx, &cc, func() error {
if err = cc.client.objectDelete(ctx, prm); err != nil {
return fmt.Errorf("remove object via client: %w", err)
return fmt.Errorf("remove object via client %s: %w", cc.endpoint, err)
}
return nil
@ -2244,7 +2244,10 @@ func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (ResGetObject, e
return res, p.call(ctx, &cc, func() error {
res, err = cc.client.objectGet(ctx, prm)
return err
if err != nil {
return fmt.Errorf("get object via client %s: %w", cc.endpoint, err)
}
return nil
})
}
@ -2266,7 +2269,10 @@ func (p *Pool) HeadObject(ctx context.Context, prm PrmObjectHead) (object.Object
return obj, p.call(ctx, &cc, func() error {
obj, err = cc.client.objectHead(ctx, prm)
return err
if err != nil {
return fmt.Errorf("head object via client %s: %w", cc.endpoint, err)
}
return nil
})
}
@ -2314,7 +2320,10 @@ func (p *Pool) ObjectRange(ctx context.Context, prm PrmObjectRange) (ResObjectRa
return res, p.call(ctx, &cc, func() error {
res, err = cc.client.objectRange(ctx, prm)
return err
if err != nil {
return fmt.Errorf("object range via client %s: %w", cc.endpoint, err)
}
return nil
})
}
@ -2375,7 +2384,10 @@ func (p *Pool) SearchObjects(ctx context.Context, prm PrmObjectSearch) (ResObjec
return res, p.call(ctx, &cc, func() error {
res, err = cc.client.objectSearch(ctx, prm)
dkirillov marked this conversation as resolved Outdated

It seems the the cc.client.objectSearch call is missed

It seems the the `cc.client.objectSearch` call is missed
return err
if err != nil {
dkirillov marked this conversation as resolved Outdated

Actually here we can use cc.endpoint instead of cc.client.address() but it's up to you

Actually here we can use `cc.endpoint` instead of `cc.client.address()` but it's up to you
return fmt.Errorf("search object via client %s: %w", cc.endpoint, err)
}
return nil
})
}
@ -2395,7 +2407,12 @@ func (p *Pool) PutContainer(ctx context.Context, prm PrmContainerPut) (cid.ID, e
return cid.ID{}, err
}
return cp.containerPut(ctx, prm)
cnrID, err := cp.containerPut(ctx, prm)
if err != nil {
return cid.ID{}, fmt.Errorf("put container via client '%s': %w", cp.address(), err)
}
return cnrID, nil
}
// GetContainer reads FrostFS container by ID.
@ -2407,7 +2424,12 @@ func (p *Pool) GetContainer(ctx context.Context, prm PrmContainerGet) (container
return container.Container{}, err
}
return cp.containerGet(ctx, prm)
cnrs, err := cp.containerGet(ctx, prm)
if err != nil {
return container.Container{}, fmt.Errorf("get container via client '%s': %w", cp.address(), err)
}
return cnrs, nil
}
// ListContainers requests identifiers of the account-owned containers.
@ -2417,7 +2439,12 @@ func (p *Pool) ListContainers(ctx context.Context, prm PrmContainerList) ([]cid.
return nil, err
}
return cp.containerList(ctx, prm)
cnrIDs, err := cp.containerList(ctx, prm)
if err != nil {
return []cid.ID{}, fmt.Errorf("list containers via client '%s': %w", cp.address(), err)
}
return cnrIDs, nil
}
// DeleteContainer sends request to remove the FrostFS container and waits for the operation to complete.
@ -2434,7 +2461,12 @@ func (p *Pool) DeleteContainer(ctx context.Context, prm PrmContainerDelete) erro
return err
}
return cp.containerDelete(ctx, prm)
err = cp.containerDelete(ctx, prm)
if err != nil {
return fmt.Errorf("delete container via client '%s': %w", cp.address(), err)
}
return nil
}
// GetEACL reads eACL table of the FrostFS container.
@ -2446,7 +2478,12 @@ func (p *Pool) GetEACL(ctx context.Context, prm PrmContainerEACL) (eacl.Table, e
return eacl.Table{}, err
}
return cp.containerEACL(ctx, prm)
eaclResult, err := cp.containerEACL(ctx, prm)
if err != nil {
return eacl.Table{}, fmt.Errorf("get EACL via client '%s': %w", cp.address(), err)
}
return eaclResult, nil
}
// SetEACL sends request to update eACL table of the FrostFS container and waits for the operation to complete.
@ -2463,7 +2500,12 @@ func (p *Pool) SetEACL(ctx context.Context, prm PrmContainerSetEACL) error {
return err
}
return cp.containerSetEACL(ctx, prm)
err = cp.containerSetEACL(ctx, prm)
if err != nil {
return fmt.Errorf("set EACL via client '%s': %w", cp.address(), err)
}
return nil
}
// Balance requests current balance of the FrostFS account.
@ -2475,15 +2517,24 @@ func (p *Pool) Balance(ctx context.Context, prm PrmBalanceGet) (accounting.Decim
return accounting.Decimal{}, err
}
return cp.balanceGet(ctx, prm)
balance, err := cp.balanceGet(ctx, prm)
if err != nil {
return accounting.Decimal{}, fmt.Errorf("get balance via client '%s': %w", cp.address(), err)
}
return balance, nil
}
// Statistic returns connection statistics.
func (p Pool) Statistic() Statistic {
stat := Statistic{}
for _, inner := range p.innerPools {
nodes := make([]string, 0, len(inner.clients))
inner.lock.RLock()
for _, cl := range inner.clients {
if cl.isHealthy() {
nodes = append(nodes, cl.address())
}
node := NodeStatistic{
address: cl.address(),
methods: cl.methodsStatus(),
@ -2494,6 +2545,9 @@ func (p Pool) Statistic() Statistic {
stat.overallErrors += node.overallErrors
}
inner.lock.RUnlock()
if len(stat.currentNodes) == 0 {
stat.currentNodes = nodes
}
}
return stat
@ -2571,7 +2625,12 @@ func (p *Pool) NetworkInfo(ctx context.Context) (netmap.NetworkInfo, error) {
return netmap.NetworkInfo{}, err
}
return cp.networkInfo(ctx, prmNetworkInfo{})
netInfo, err := cp.networkInfo(ctx, prmNetworkInfo{})
if err != nil {
return netmap.NetworkInfo{}, fmt.Errorf("get network info via client '%s': %w", cp.address(), err)
}
return netInfo, nil
}
// Close closes the Pool and releases all the associated resources.

View file

@ -9,6 +9,7 @@ import (
type Statistic struct {
overallErrors uint64
nodes []NodeStatistic
currentNodes []string
dkirillov marked this conversation as resolved Outdated

We need getter for this field

We need getter for this field
}
// OverallErrors returns sum of errors on all connections. It doesn't decrease.
@ -21,6 +22,12 @@ func (s Statistic) Nodes() []NodeStatistic {
return s.nodes
}
// CurrentNodes returns list of nodes of inner pool that has at least one healthy node.
dkirillov marked this conversation as resolved Outdated

Let's mention that these nodes have the same priority and this priority is the highest among inner pool with healthy nodes

Let's mention that these nodes have the same priority and this priority is the highest among inner pool with healthy nodes
// These nodes have the same and the highest priority among the other healthy nodes.
func (s Statistic) CurrentNodes() []string {
return s.currentNodes
}
// ErrUnknownNode indicate that node with current address is not found in list.
var ErrUnknownNode = errors.New("unknown node")