2019-06-26 19:55:22 +01:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package nodestats
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-07-02 13:05:58 +01:00
|
|
|
"time"
|
2019-06-26 19:55:22 +01:00
|
|
|
|
2019-11-08 20:40:39 +00:00
|
|
|
"github.com/spacemonkeygo/monkit/v3"
|
2019-06-26 19:55:22 +01:00
|
|
|
"github.com/zeebo/errs"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
2019-12-27 11:48:47 +00:00
|
|
|
"storj.io/common/pb"
|
|
|
|
"storj.io/common/rpc"
|
|
|
|
"storj.io/common/storj"
|
2020-04-10 15:03:14 +01:00
|
|
|
"storj.io/storj/storagenode/pricing"
|
2019-08-08 14:47:04 +01:00
|
|
|
"storj.io/storj/storagenode/reputation"
|
|
|
|
"storj.io/storj/storagenode/storageusage"
|
|
|
|
"storj.io/storj/storagenode/trust"
|
2019-06-26 19:55:22 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2020-08-11 15:50:01 +01:00
|
|
|
// NodeStatsServiceErr defines node stats service error.
|
2021-04-28 09:06:17 +01:00
|
|
|
NodeStatsServiceErr = errs.Class("nodestats")
|
2019-06-26 19:55:22 +01:00
|
|
|
|
|
|
|
mon = monkit.Package()
|
|
|
|
)
|
|
|
|
|
2020-12-05 16:01:42 +00:00
|
|
|
// Client encapsulates NodeStatsClient with underlying connection.
|
2019-09-10 14:24:16 +01:00
|
|
|
//
|
|
|
|
// architecture: Client
|
2019-07-04 11:34:23 +01:00
|
|
|
type Client struct {
|
2019-09-19 05:46:39 +01:00
|
|
|
conn *rpc.Conn
|
2019-12-22 14:52:55 +00:00
|
|
|
pb.DRPCNodeStatsClient
|
2019-07-04 11:34:23 +01:00
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// Close closes underlying client connection.
|
2019-07-04 11:34:23 +01:00
|
|
|
func (c *Client) Close() error {
|
|
|
|
return c.conn.Close()
|
|
|
|
}
|
|
|
|
|
2020-12-05 16:01:42 +00:00
|
|
|
// Service retrieves info from satellites using an rpc client.
|
2019-09-10 14:24:16 +01:00
|
|
|
//
|
|
|
|
// architecture: Service
|
2019-06-26 19:55:22 +01:00
|
|
|
type Service struct {
|
|
|
|
log *zap.Logger
|
|
|
|
|
2019-09-19 05:46:39 +01:00
|
|
|
dialer rpc.Dialer
|
|
|
|
trust *trust.Pool
|
2019-06-26 19:55:22 +01:00
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// NewService creates new instance of service.
|
2019-09-19 05:46:39 +01:00
|
|
|
func NewService(log *zap.Logger, dialer rpc.Dialer, trust *trust.Pool) *Service {
|
2019-06-26 19:55:22 +01:00
|
|
|
return &Service{
|
2019-09-19 05:46:39 +01:00
|
|
|
log: log,
|
|
|
|
dialer: dialer,
|
|
|
|
trust: trust,
|
2019-06-26 19:55:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// GetReputationStats retrieves reputation stats from particular satellite.
|
2019-08-08 14:47:04 +01:00
|
|
|
func (s *Service) GetReputationStats(ctx context.Context, satelliteID storj.NodeID) (_ *reputation.Stats, err error) {
|
2019-06-26 19:55:22 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2019-08-08 14:47:04 +01:00
|
|
|
client, err := s.dial(ctx, satelliteID)
|
2019-06-26 19:55:22 +01:00
|
|
|
if err != nil {
|
2019-07-02 13:05:58 +01:00
|
|
|
return nil, NodeStatsServiceErr.Wrap(err)
|
2019-06-26 19:55:22 +01:00
|
|
|
}
|
2019-09-19 05:46:39 +01:00
|
|
|
defer func() { err = errs.Combine(err, client.Close()) }()
|
2019-07-04 11:34:23 +01:00
|
|
|
|
2019-07-08 15:33:43 +01:00
|
|
|
resp, err := client.GetStats(ctx, &pb.GetStatsRequest{})
|
2019-06-26 19:55:22 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, NodeStatsServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
2019-07-08 15:33:43 +01:00
|
|
|
audit := resp.GetAuditCheck()
|
|
|
|
|
2022-09-13 14:29:41 +01:00
|
|
|
satelliteIDSeriesTag := monkit.NewSeriesTag("satellite_id", satelliteID.String())
|
|
|
|
|
|
|
|
mon.IntVal("audit_success_count", satelliteIDSeriesTag).Observe(audit.GetSuccessCount())
|
|
|
|
mon.IntVal("audit_total_count", satelliteIDSeriesTag).Observe(audit.GetTotalCount())
|
|
|
|
mon.FloatVal("audit_reputation_score", satelliteIDSeriesTag).Observe(audit.GetReputationScore())
|
|
|
|
mon.FloatVal("suspension_score", satelliteIDSeriesTag).Observe(audit.GetUnknownReputationScore())
|
|
|
|
mon.FloatVal("online_score", satelliteIDSeriesTag).Observe(resp.GetOnlineScore())
|
|
|
|
|
2019-08-08 14:47:04 +01:00
|
|
|
return &reputation.Stats{
|
2019-07-08 15:33:43 +01:00
|
|
|
SatelliteID: satelliteID,
|
2019-08-08 14:47:04 +01:00
|
|
|
Audit: reputation.Metric{
|
|
|
|
TotalCount: audit.GetTotalCount(),
|
|
|
|
SuccessCount: audit.GetSuccessCount(),
|
|
|
|
Alpha: audit.GetReputationAlpha(),
|
|
|
|
Beta: audit.GetReputationBeta(),
|
|
|
|
Score: audit.GetReputationScore(),
|
2020-05-03 17:30:54 +01:00
|
|
|
UnknownAlpha: audit.GetUnknownReputationAlpha(),
|
|
|
|
UnknownBeta: audit.GetUnknownReputationBeta(),
|
2020-06-12 14:43:11 +01:00
|
|
|
UnknownScore: audit.GetUnknownReputationScore(),
|
2019-07-08 15:33:43 +01:00
|
|
|
},
|
2020-09-02 16:37:54 +01:00
|
|
|
OnlineScore: resp.OnlineScore,
|
|
|
|
DisqualifiedAt: resp.GetDisqualified(),
|
|
|
|
SuspendedAt: resp.GetSuspended(),
|
|
|
|
OfflineSuspendedAt: resp.GetOfflineSuspended(),
|
|
|
|
OfflineUnderReviewAt: resp.GetOfflineUnderReview(),
|
2021-07-02 14:13:13 +01:00
|
|
|
VettedAt: resp.GetVettedAt(),
|
2020-12-11 21:15:17 +00:00
|
|
|
AuditHistory: resp.GetAuditHistory(),
|
2020-09-02 16:37:54 +01:00
|
|
|
UpdatedAt: time.Now(),
|
|
|
|
JoinedAt: resp.JoinedAt,
|
2019-06-26 19:55:22 +01:00
|
|
|
}, nil
|
|
|
|
}
|
2019-07-02 13:05:58 +01:00
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// GetDailyStorageUsage returns daily storage usage over a period of time for a particular satellite.
|
2019-08-08 14:47:04 +01:00
|
|
|
func (s *Service) GetDailyStorageUsage(ctx context.Context, satelliteID storj.NodeID, from, to time.Time) (_ []storageusage.Stamp, err error) {
|
2019-07-02 13:05:58 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2019-08-08 14:47:04 +01:00
|
|
|
client, err := s.dial(ctx, satelliteID)
|
2019-07-02 13:05:58 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, NodeStatsServiceErr.Wrap(err)
|
|
|
|
}
|
2019-09-19 05:46:39 +01:00
|
|
|
defer func() { err = errs.Combine(err, client.Close()) }()
|
2019-07-04 11:34:23 +01:00
|
|
|
|
2019-08-08 14:47:04 +01:00
|
|
|
resp, err := client.DailyStorageUsage(ctx, &pb.DailyStorageUsageRequest{From: from, To: to})
|
2019-07-02 13:05:58 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, NodeStatsServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return fromSpaceUsageResponse(resp, satelliteID), nil
|
|
|
|
}
|
|
|
|
|
2020-04-10 15:03:14 +01:00
|
|
|
// GetPricingModel returns pricing model of specific satellite.
|
|
|
|
func (s *Service) GetPricingModel(ctx context.Context, satelliteID storj.NodeID) (_ *pricing.Pricing, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
client, err := s.dial(ctx, satelliteID)
|
|
|
|
if err != nil {
|
|
|
|
return nil, NodeStatsServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
defer func() { err = errs.Combine(err, client.Close()) }()
|
|
|
|
|
|
|
|
pricingModel, err := client.PricingModel(ctx, &pb.PricingModelRequest{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, NodeStatsServiceErr.Wrap(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &pricing.Pricing{
|
|
|
|
SatelliteID: satelliteID,
|
|
|
|
EgressBandwidth: pricingModel.EgressBandwidthPrice,
|
|
|
|
RepairBandwidth: pricingModel.RepairBandwidthPrice,
|
|
|
|
AuditBandwidth: pricingModel.AuditBandwidthPrice,
|
|
|
|
DiskSpace: pricingModel.DiskSpacePrice,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// dial dials the NodeStats client for the satellite by id.
|
2019-08-08 14:47:04 +01:00
|
|
|
func (s *Service) dial(ctx context.Context, satelliteID storj.NodeID) (_ *Client, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2020-05-19 17:11:30 +01:00
|
|
|
nodeurl, err := s.trust.GetNodeURL(ctx, satelliteID)
|
2019-07-02 13:05:58 +01:00
|
|
|
if err != nil {
|
2020-01-14 11:41:12 +00:00
|
|
|
return nil, errs.New("unable to find satellite %s: %w", satelliteID, err)
|
2019-07-02 13:05:58 +01:00
|
|
|
}
|
|
|
|
|
2020-05-19 17:11:30 +01:00
|
|
|
conn, err := s.dialer.DialNodeURL(ctx, nodeurl)
|
2019-07-02 13:05:58 +01:00
|
|
|
if err != nil {
|
2020-01-14 11:41:12 +00:00
|
|
|
return nil, errs.New("unable to connect to the satellite %s: %w", satelliteID, err)
|
2019-07-02 13:05:58 +01:00
|
|
|
}
|
|
|
|
|
2019-07-04 11:34:23 +01:00
|
|
|
return &Client{
|
2019-12-22 14:52:55 +00:00
|
|
|
conn: conn,
|
2020-03-25 12:15:27 +00:00
|
|
|
DRPCNodeStatsClient: pb.NewDRPCNodeStatsClient(conn),
|
2019-07-04 11:34:23 +01:00
|
|
|
}, nil
|
2019-07-02 13:05:58 +01:00
|
|
|
}
|
|
|
|
|
2020-07-16 15:18:02 +01:00
|
|
|
// fromSpaceUsageResponse get DiskSpaceUsage slice from pb.SpaceUsageResponse.
|
2019-08-08 14:47:04 +01:00
|
|
|
func fromSpaceUsageResponse(resp *pb.DailyStorageUsageResponse, satelliteID storj.NodeID) []storageusage.Stamp {
|
|
|
|
var stamps []storageusage.Stamp
|
2019-07-02 13:05:58 +01:00
|
|
|
|
|
|
|
for _, pbUsage := range resp.GetDailyStorageUsage() {
|
2019-08-08 14:47:04 +01:00
|
|
|
stamps = append(stamps, storageusage.Stamp{
|
2022-07-21 12:15:03 +01:00
|
|
|
SatelliteID: satelliteID,
|
|
|
|
AtRestTotal: pbUsage.AtRestTotal,
|
|
|
|
IntervalStart: pbUsage.Timestamp,
|
|
|
|
IntervalEndTime: pbUsage.IntervalEndTime,
|
2019-07-02 13:05:58 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return stamps
|
|
|
|
}
|