payments accesses database directly (#1135)
* move payments command into satellite/main.go * flag for db connection string in paymentsCmd * refactor payments to satellite subcommand * reports command, add payments arg descriptions * report data prints to stdout unless --out is set * fix small error in csv columns
This commit is contained in:
parent
6025f9f19e
commit
1403b15cc7
@ -10,6 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/zeebo/errs"
|
||||
@ -57,6 +58,17 @@ var (
|
||||
Short: "Repair Queue Diagnostic Tool support",
|
||||
RunE: cmdQDiag,
|
||||
}
|
||||
reportsCmd = &cobra.Command{
|
||||
Use: "reports",
|
||||
Short: "Generate a report",
|
||||
}
|
||||
paymentsCmd = &cobra.Command{
|
||||
Use: "payments [start] [end]",
|
||||
Short: "Generate a payment report for a given period",
|
||||
Long: "Generate a payment report for a given period. Format dates using YYYY-MM-DD",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
RunE: cmdPayments,
|
||||
}
|
||||
|
||||
runCfg Satellite
|
||||
setupCfg Satellite
|
||||
@ -68,6 +80,10 @@ var (
|
||||
Database string `help:"satellite database connection string" default:"sqlite3://$CONFDIR/master.db"`
|
||||
QListLimit int `help:"maximum segments that can be requested" default:"1000"`
|
||||
}
|
||||
paymentsCfg struct {
|
||||
Database string `help:"satellite database connection string" default:"sqlite3://$CONFDIR/master.db"`
|
||||
Output string `help:"destination of report output" default:""`
|
||||
}
|
||||
|
||||
defaultConfDir = fpath.ApplicationDir("storj", "satellite")
|
||||
// TODO: this path should be defined somewhere else
|
||||
@ -101,10 +117,13 @@ func init() {
|
||||
rootCmd.AddCommand(setupCmd)
|
||||
rootCmd.AddCommand(diagCmd)
|
||||
rootCmd.AddCommand(qdiagCmd)
|
||||
rootCmd.AddCommand(reportsCmd)
|
||||
reportsCmd.AddCommand(paymentsCmd)
|
||||
cfgstruct.Bind(runCmd.Flags(), &runCfg, cfgstruct.ConfDir(defaultConfDir), cfgstruct.IdentityDir(defaultIdentityDir))
|
||||
cfgstruct.BindSetup(setupCmd.Flags(), &setupCfg, cfgstruct.ConfDir(defaultConfDir), cfgstruct.IdentityDir(defaultIdentityDir))
|
||||
cfgstruct.Bind(diagCmd.Flags(), &diagCfg, cfgstruct.ConfDir(defaultConfDir), cfgstruct.IdentityDir(defaultIdentityDir))
|
||||
cfgstruct.Bind(qdiagCmd.Flags(), &qdiagCfg, cfgstruct.ConfDir(defaultConfDir), cfgstruct.IdentityDir(defaultIdentityDir))
|
||||
cfgstruct.Bind(paymentsCmd.Flags(), &paymentsCfg, cfgstruct.ConfDir(defaultConfDir), cfgstruct.IdentityDir(defaultIdentityDir))
|
||||
}
|
||||
|
||||
func cmdRun(cmd *cobra.Command, args []string) (err error) {
|
||||
@ -268,6 +287,42 @@ func cmdQDiag(cmd *cobra.Command, args []string) (err error) {
|
||||
return w.Flush()
|
||||
}
|
||||
|
||||
func cmdPayments(cmd *cobra.Command, args []string) (err error) {
|
||||
ctx := process.Ctx(cmd)
|
||||
|
||||
layout := "2006-01-02"
|
||||
start, err := time.Parse(layout, args[0])
|
||||
if err != nil {
|
||||
return errs.New("Invalid date format. Please use YYYY-MM-DD")
|
||||
}
|
||||
end, err := time.Parse(layout, args[1])
|
||||
if err != nil {
|
||||
return errs.New("Invalid date format. Please use YYYY-MM-DD")
|
||||
}
|
||||
|
||||
// Ensure that start date is not after end date
|
||||
if start.After(end) {
|
||||
return errs.New("Invalid time period (%v) - (%v)", start, end)
|
||||
}
|
||||
|
||||
// send output to stdout
|
||||
if paymentsCfg.Output == "" {
|
||||
return generateCSV(ctx, start, end, os.Stdout)
|
||||
}
|
||||
|
||||
// send output to file
|
||||
file, err := os.Create(paymentsCfg.Output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err = errs.Combine(err, file.Close())
|
||||
}()
|
||||
|
||||
return generateCSV(ctx, start, end, file)
|
||||
}
|
||||
|
||||
func main() {
|
||||
process.Exec(rootCmd)
|
||||
}
|
||||
|
91
cmd/satellite/payments.go
Normal file
91
cmd/satellite/payments.go
Normal file
@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2019 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
|
||||
"storj.io/storj/pkg/accounting"
|
||||
"storj.io/storj/satellite/satellitedb"
|
||||
)
|
||||
|
||||
// generateCSV generates a payment report for all nodes for a given period
|
||||
func generateCSV(ctx context.Context, start time.Time, end time.Time, output io.Writer) error {
|
||||
db, err := satellitedb.New(paymentsCfg.Database)
|
||||
if err != nil {
|
||||
return errs.New("error connecting to master database on satellite: %+v", err)
|
||||
}
|
||||
defer func() {
|
||||
err = errs.Combine(err, db.Close())
|
||||
}()
|
||||
|
||||
rows, err := db.Accounting().QueryPaymentInfo(ctx, start, end)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w := csv.NewWriter(output)
|
||||
headers := []string{
|
||||
"nodeID",
|
||||
"nodeCreationDate",
|
||||
"auditSuccessRatio",
|
||||
"byte-hours:AtRest",
|
||||
"bytes:BWRepair-GET",
|
||||
"bytes:BWRepair-PUT",
|
||||
"bytes:BWAudit",
|
||||
"bytes:BWGet",
|
||||
"bytes:BWPut",
|
||||
"date",
|
||||
"walletAddress",
|
||||
}
|
||||
if err := w.Write(headers); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, row := range rows {
|
||||
nid := row.NodeID
|
||||
wallet, err := db.OverlayCache().GetWalletAddress(ctx, nid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
row.Wallet = wallet
|
||||
record := structToStringSlice(row)
|
||||
if err := w.Write(record); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := w.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
w.Flush()
|
||||
if output != os.Stdout {
|
||||
fmt.Println("Generated payment report")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func structToStringSlice(s *accounting.CSVRow) []string {
|
||||
record := []string{
|
||||
s.NodeID.String(),
|
||||
s.NodeCreationDate.Format("2006-01-02"),
|
||||
strconv.FormatFloat(s.AuditSuccessRatio, 'f', 5, 64),
|
||||
strconv.FormatFloat(s.AtRestTotal, 'f', 5, 64),
|
||||
strconv.FormatInt(s.GetRepairTotal, 10),
|
||||
strconv.FormatInt(s.PutRepairTotal, 10),
|
||||
strconv.FormatInt(s.GetAuditTotal, 10),
|
||||
strconv.FormatInt(s.GetTotal, 10),
|
||||
strconv.FormatInt(s.PutTotal, 10),
|
||||
s.Date.Format("2006-01-02"),
|
||||
s.Wallet,
|
||||
}
|
||||
return record
|
||||
}
|
Loading…
Reference in New Issue
Block a user