cmd/lncli: add fwdinghistory support for relative times

- introduces new parser in `cmd/lncli/arg_parse.go`
- converts start_time and end_time flags to strings
- adds default value for end_time
This commit is contained in:
Jasper Rädisch 2019-05-09 22:04:39 +02:00 committed by Olaoluwa Osuntokun
parent 03b20cabd2
commit 20b42ce261
3 changed files with 153 additions and 19 deletions

40
cmd/lncli/arg_parse.go Normal file

@ -0,0 +1,40 @@
package main
import (
"regexp"
"strconv"
"time"
)
// reTimeRange matches systemd.time-like short negative timeranges, e.g. "-200s".
var reTimeRange = regexp.MustCompile(`^-\d{1,18}[s|m|h|d|w|M|y]$`)
// secondsPer allows translating s(seconds), m(minutes), h(ours), d(ays),
// w(eeks), M(onths) and y(ears) into corresponding seconds.
var secondsPer = map[string]int64{
"s": 1,
"m": 60,
"h": 3600,
"d": 86400,
"w": 604800,
"M": 2630016, // 30.44 days
"y": 31557600, // 365.25 days
}
// parseTime parses UNIX timestamps or short timeranges inspired by sytemd (when starting with "-"),
// e.g. "-1M" for one month (30.44 days) ago.
func parseTime(s string, base time.Time) (uint64, error) {
if reTimeRange.MatchString(s) {
last := len(s) - 1
d, err := strconv.ParseInt(s[1:last], 10, 64)
if err != nil {
return uint64(0), err
}
mul := secondsPer[string(s[last])]
return uint64(base.Unix() - d*mul), nil
}
return strconv.ParseUint(s, 10, 64)
}

@ -0,0 +1,88 @@
package main
import (
"testing"
"time"
)
var now = time.Date(2017, 11, 10, 7, 8, 9, 1234, time.UTC)
var partTimeTests = []struct {
in string
expected uint64
errExpected bool
}{
{
"12345",
uint64(12345),
false,
},
{
"-0s",
uint64(now.Unix()),
false,
},
{
"-1s",
uint64(time.Date(2017, 11, 10, 7, 8, 8, 1234, time.UTC).Unix()),
false,
},
{
"-2h",
uint64(time.Date(2017, 11, 10, 5, 8, 9, 1234, time.UTC).Unix()),
false,
},
{
"-3d",
uint64(time.Date(2017, 11, 7, 7, 8, 9, 1234, time.UTC).Unix()),
false,
},
{
"-4w",
uint64(time.Date(2017, 10, 13, 7, 8, 9, 1234, time.UTC).Unix()),
false,
},
{
"-5M",
uint64(now.Unix() - 30.44*5*24*60*60),
false,
},
{
"-6y",
uint64(now.Unix() - 365.25*6*24*60*60),
false,
},
{
"-999999999999999999s",
uint64(now.Unix() - 999999999999999999),
false,
},
{
"-9999999999999999991s",
0,
true,
},
{
"-7z",
0,
true,
},
}
// Test that parsing absolute and relative times works.
func TestParseTime(t *testing.T) {
for _, test := range partTimeTests {
actual, err := parseTime(test.in, now)
if test.errExpected == (err == nil) {
t.Fatalf("unexpected error for %s:\n%v\n", test.in, err)
}
if actual != test.expected {
t.Fatalf(
"for %s actual and expected do not match:\n%d\n%d\n",
test.in,
actual,
test.expected,
)
}
}
}

@ -2708,9 +2708,12 @@ var forwardingHistoryCommand = cli.Command{
Query the HTLC switch's internal forwarding log for all completed
payment circuits (HTLCs) over a particular time range (--start_time and
--end_time). The start and end times are meant to be expressed in
seconds since the Unix epoch. If --start_time isn't provided,
then 24 hours ago is used. If --end_time isn't provided,
then the current time is used.
seconds since the Unix epoch.
Alternatively negative time ranges can be used, e.g. "-3d". Supports
s(seconds), m(minutes), h(ours), d(ays), w(eeks), M(onths), y(ears).
Month equals 30.44 days, year equals 365.25 days.
If --start_time isn't provided, then 24 hours ago is used. If
--end_time isn't provided, then the current time is used.
The max number of events returned is 50k. The default number is 100,
callers can use the --max_events param to modify this value.
@ -2720,15 +2723,15 @@ var forwardingHistoryCommand = cli.Command{
entry. Using this callers can manually paginate within a time slice.
`,
Flags: []cli.Flag{
cli.Int64Flag{
cli.StringFlag{
Name: "start_time",
Usage: "the starting time for the query, expressed in " +
"seconds since the unix epoch",
Usage: "the starting time for the query " +
`as unix timestamp or relative e.g. "-1w"`,
},
cli.Int64Flag{
cli.StringFlag{
Name: "end_time",
Usage: "the end time for the query, expressed in " +
"seconds since the unix epoch",
Usage: "the end time for the query " +
`as unix timestamp or relative e.g. "-1w"`,
},
cli.Int64Flag{
Name: "index_offset",
@ -2753,31 +2756,34 @@ func forwardingHistory(ctx *cli.Context) error {
err error
)
args := ctx.Args()
now := time.Now()
switch {
case ctx.IsSet("start_time"):
startTime = ctx.Uint64("start_time")
startTime, err = parseTime(ctx.String("start_time"), now)
case args.Present():
startTime, err = strconv.ParseUint(args.First(), 10, 64)
if err != nil {
return fmt.Errorf("unable to decode start_time %v", err)
}
startTime, err = parseTime(args.First(), now)
args = args.Tail()
default:
now := time.Now()
startTime = uint64(now.Add(-time.Hour * 24).Unix())
}
if err != nil {
return fmt.Errorf("unable to decode start_time: %v", err)
}
switch {
case ctx.IsSet("end_time"):
endTime = ctx.Uint64("end_time")
endTime, err = parseTime(ctx.String("end_time"), now)
case args.Present():
endTime, err = strconv.ParseUint(args.First(), 10, 64)
endTime, err = parseTime(args.First(), now)
args = args.Tail()
default:
endTime = uint64(now.Unix())
}
if err != nil {
return fmt.Errorf("unable to decode end_time: %v", err)
}
args = args.Tail()
}
switch {
case ctx.IsSet("index_offset"):