storj/storagenode/inspector/inspector.go
Isaac Hess 14fd6a9ef0 storagenode/pieces: Track total piece size
This change updates the storagenode piecestore apis to expose access to
the full piece size stored on disk. Previously we only had access to
(and only kept a cache of) the content size used for all pieces. This
was inaccurate when reporting the amount of disk space used by nodes.

We now have access to the total content size, as well as the total disk
usage, of all pieces. The pieces cache also keeps a cache of the total
piece size along with the content size.

Change-Id: I4fffe7e1257e04c46021a2e37c5adc6fe69bee55
2020-01-23 11:00:24 -07:00

130 lines
3.7 KiB
Go

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package inspector
import (
"context"
"net"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/zeebo/errs"
"go.uber.org/zap"
"gopkg.in/spacemonkeygo/monkit.v2"
"storj.io/common/pb"
"storj.io/common/rpc/rpcstatus"
"storj.io/storj/storagenode/bandwidth"
"storj.io/storj/storagenode/contact"
"storj.io/storj/storagenode/pieces"
"storj.io/storj/storagenode/piecestore"
)
var (
mon = monkit.Package()
// Error is the default error class for piecestore monitor errors
Error = errs.Class("piecestore inspector")
)
// Endpoint does inspectory things
//
// architecture: Endpoint
type Endpoint struct {
log *zap.Logger
pieceStore *pieces.Store
contact *contact.Service
pingStats *contact.PingStats
usageDB bandwidth.DB
startTime time.Time
pieceStoreConfig piecestore.OldConfig
dashboardAddress net.Addr
externalAddress string
}
// NewEndpoint creates piecestore inspector instance
func NewEndpoint(
log *zap.Logger,
pieceStore *pieces.Store,
contact *contact.Service,
pingStats *contact.PingStats,
usageDB bandwidth.DB,
pieceStoreConfig piecestore.OldConfig,
dashboardAddress net.Addr,
externalAddress string) *Endpoint {
return &Endpoint{
log: log,
pieceStore: pieceStore,
contact: contact,
pingStats: pingStats,
usageDB: usageDB,
pieceStoreConfig: pieceStoreConfig,
dashboardAddress: dashboardAddress,
startTime: time.Now(),
externalAddress: externalAddress,
}
}
// Stats returns current statistics about the storage node
func (inspector *Endpoint) Stats(ctx context.Context, in *pb.StatsRequest) (out *pb.StatSummaryResponse, err error) {
defer mon.Task()(&ctx)(&err)
return inspector.retrieveStats(ctx)
}
func (inspector *Endpoint) retrieveStats(ctx context.Context) (_ *pb.StatSummaryResponse, err error) {
defer mon.Task()(&ctx)(&err)
// Space Usage
_, piecesContentSize, err := inspector.pieceStore.SpaceUsedForPieces(ctx)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
}
usage, err := bandwidth.TotalMonthlySummary(ctx, inspector.usageDB)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
}
ingress := usage.Put + usage.PutRepair
egress := usage.Get + usage.GetAudit + usage.GetRepair
totalUsedBandwidth := usage.Total()
return &pb.StatSummaryResponse{
UsedSpace: piecesContentSize,
AvailableSpace: inspector.pieceStoreConfig.AllocatedDiskSpace.Int64() - piecesContentSize,
UsedIngress: ingress,
UsedEgress: egress,
UsedBandwidth: totalUsedBandwidth,
AvailableBandwidth: inspector.pieceStoreConfig.AllocatedBandwidth.Int64() - totalUsedBandwidth,
}, nil
}
// Dashboard returns dashboard information
func (inspector *Endpoint) Dashboard(ctx context.Context, in *pb.DashboardRequest) (out *pb.DashboardResponse, err error) {
defer mon.Task()(&ctx)(&err)
return inspector.getDashboardData(ctx)
}
func (inspector *Endpoint) getDashboardData(ctx context.Context) (_ *pb.DashboardResponse, err error) {
defer mon.Task()(&ctx)(&err)
statsSummary, err := inspector.retrieveStats(ctx)
if err != nil {
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
}
lastPingedAt := inspector.pingStats.WhenLastPinged()
return &pb.DashboardResponse{
NodeId: inspector.contact.Local().Id,
InternalAddress: "",
ExternalAddress: inspector.contact.Local().Address.Address,
LastPinged: lastPingedAt,
DashboardAddress: inspector.dashboardAddress.String(),
Uptime: ptypes.DurationProto(time.Since(inspector.startTime)),
Stats: statsSummary,
}, nil
}