Skip to content

Commit

Permalink
feat: add history command (jsdelivr#97)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Kolárik <[email protected]>
  • Loading branch information
radulucut and MartinKolarik authored Mar 27, 2024
1 parent 2c844ae commit c522c89
Show file tree
Hide file tree
Showing 20 changed files with 612 additions and 107 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Measurement Commands:
Additional Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
history Show the history of your measurements in your current session
install-probe Join the community powered Globalping platform by running a Docker container.
version Print the version number of Globalping CLI

Expand Down Expand Up @@ -307,6 +308,24 @@ Madrid, ES, EU, EDGOO NETWORKS LLC (AS47787) | 22 | 0.00% | 0.24
^C
```
#### History
You can view the history of your measurements by running the `history` command.
```bash
globalping history
1 | 2024-03-27 11:56:46 | ping google.com
> https://www.jsdelivr.com/globalping?measurement=itcR65tYCqbouXib
- | 2024-03-27 11:57:01 | dns google.com from last
> https://www.jsdelivr.com/globalping?measurement=kWc5UBK9A6G4RUYM
2 | 2024-03-27 11:57:20 | traceroute google.com from New York --limit 2
> https://www.jsdelivr.com/globalping?measurement=Yz7A1UifUonZsC3C
3 | 2024-03-27 11:57:37 | mtr google.com from New York --limit 2
> https://www.jsdelivr.com/globalping?measurement=SX1NBgfDKiabM1vZ
4 | 2024-03-27 11:57:52 | http google.com from London,Belgium --limit 2 --method get --ci
> https://www.jsdelivr.com/globalping?measurement=eclwFSYX0zgU10Cs
```
#### Learn about available flags
Most commands have shared and unique flags. We recommend that you familiarize yourself with these so that you can run and automate your network tests in powerful ways.
Expand Down
33 changes: 21 additions & 12 deletions cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ import (
)

var (
ErrorNoPreviousMeasurements = errors.New("no previous measurements found")
ErrInvalidIndex = errors.New("invalid index")
ErrIndexOutOfRange = errors.New("index out of range")
ErrNoPreviousMeasurements = errors.New("no previous measurements found")
ErrInvalidIndex = errors.New("invalid index")
ErrIndexOutOfRange = errors.New("index out of range")
)
var (
saveIdToSessionErr = "failed to save measurement ID: %s"
readMeasuremetsErr = "failed to read previous measurements: %s"
)

var SESSION_PATH string
Expand Down Expand Up @@ -78,6 +82,7 @@ func (r *Root) getLocations() ([]globalping.Locations, error) {
if mId == "" {
mId = strings.TrimSpace(fromArr[0])
} else {
r.ctx.IsLocationFromSession = true
r.ctx.RecordToSession = false
}
return []globalping.Locations{{Magic: mId}}, nil
Expand Down Expand Up @@ -182,19 +187,19 @@ func getIdFromSession(index int) (string, error) {
f, err := os.Open(getMeasurementsPath())
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return "", ErrorNoPreviousMeasurements
return "", ErrNoPreviousMeasurements
}
return "", fmt.Errorf("failed to open previous measurements file: %s", err)
return "", fmt.Errorf(readMeasuremetsErr, err)
}
defer f.Close()
// Read ids from the end of the file
if index < 0 {
fStats, err := f.Stat()
if err != nil {
return "", fmt.Errorf("failed to read previous measurements: %s", err)
return "", fmt.Errorf(readMeasuremetsErr, err)
}
if fStats.Size() == 0 {
return "", ErrorNoPreviousMeasurements
return "", ErrNoPreviousMeasurements
}
scanner := backscanner.New(f, int(fStats.Size()-1)) // -1 to skip last newline
for {
Expand All @@ -204,7 +209,7 @@ func getIdFromSession(index int) (string, error) {
if err == io.EOF {
return "", ErrIndexOutOfRange
}
return "", fmt.Errorf("failed to read previous measurements: %s", err)
return "", fmt.Errorf(readMeasuremetsErr, err)
}
if index == 0 {
return string(b), nil
Expand Down Expand Up @@ -232,20 +237,20 @@ func saveIdToSession(id string) error {
if errors.Is(err, fs.ErrNotExist) {
err := os.Mkdir(getSessionPath(), 0755)
if err != nil {
return fmt.Errorf("failed to save measurement ID: %s", err)
return fmt.Errorf(saveIdToSessionErr, err)
}
} else {
return fmt.Errorf("failed to save measurement ID: %s", err)
return fmt.Errorf(saveIdToSessionErr, err)
}
}
f, err := os.OpenFile(getMeasurementsPath(), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return fmt.Errorf("failed to save measurement ID: %s", err)
return fmt.Errorf(saveIdToSessionErr, err)
}
defer f.Close()
_, err = f.WriteString(id + "\n")
if err != nil {
return fmt.Errorf("failed to save measurement ID: %s", err)
return fmt.Errorf(saveIdToSessionErr, err)
}
return nil
}
Expand Down Expand Up @@ -282,3 +287,7 @@ func getSessionId() string {
func getMeasurementsPath() string {
return filepath.Join(getSessionPath(), "measurements")
}

func getHistoryPath() string {
return filepath.Join(getSessionPath(), "history")
}
10 changes: 5 additions & 5 deletions cmd/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func Test_UpdateContext(t *testing.T) {
}

func test_updateContext_NoArg(t *testing.T) {
ctx := &view.Context{}
ctx := createDefaultContext("ping")
printer := view.NewPrinter(nil, nil, nil)
root := NewRoot(printer, ctx, nil, nil, nil, nil)

Expand All @@ -35,7 +35,7 @@ func test_updateContext_NoArg(t *testing.T) {
}

func test_updateContext_Country(t *testing.T) {
ctx := &view.Context{}
ctx := createDefaultContext("ping")
printer := view.NewPrinter(nil, nil, nil)
root := NewRoot(printer, ctx, nil, nil, nil, nil)

Expand All @@ -48,7 +48,7 @@ func test_updateContext_Country(t *testing.T) {

// Check if country with whitespace is parsed correctly
func test_updateContext_CountryWhitespace(t *testing.T) {
ctx := &view.Context{}
ctx := createDefaultContext("ping")
printer := view.NewPrinter(nil, nil, nil)
root := NewRoot(printer, ctx, nil, nil, nil, nil)

Expand All @@ -60,7 +60,7 @@ func test_updateContext_CountryWhitespace(t *testing.T) {
}

func test_updateContext_NoTarget(t *testing.T) {
ctx := &view.Context{}
ctx := createDefaultContext("ping")
printer := view.NewPrinter(nil, nil, nil)
root := NewRoot(printer, ctx, nil, nil, nil, nil)

Expand All @@ -73,7 +73,7 @@ func test_uodateContext_CIEnv(t *testing.T) {
t.Setenv("CI", "true")
defer t.Setenv("CI", oldCI)

ctx := &view.Context{}
ctx := createDefaultContext("ping")
printer := view.NewPrinter(nil, nil, nil)
root := NewRoot(printer, ctx, nil, nil, nil, nil)

Expand Down
19 changes: 13 additions & 6 deletions cmd/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"github.com/jsdelivr/globalping-cli/globalping"
"github.com/jsdelivr/globalping-cli/view"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -53,11 +54,11 @@ Using the dig format @resolver. For example:

// dns specific flags
flags := dnsCmd.Flags()
flags.StringVar(&r.ctx.Protocol, "protocol", "", "Specifies the protocol to use for the DNS query (TCP or UDP) (default \"udp\")")
flags.IntVar(&r.ctx.Port, "port", 0, "Send the query to a non-standard port on the server (default 53)")
flags.StringVar(&r.ctx.Resolver, "resolver", "", "Resolver is the hostname or IP address of the name server to use (default empty)")
flags.StringVar(&r.ctx.QueryType, "type", "", "Specifies the type of DNS query to perform (default \"A\")")
flags.BoolVar(&r.ctx.Trace, "trace", false, "Toggle tracing of the delegation path from the root name servers (default false)")
flags.StringVar(&r.ctx.Protocol, "protocol", r.ctx.Protocol, "Specifies the protocol to use for the DNS query (TCP or UDP) (default \"udp\")")
flags.IntVar(&r.ctx.Port, "port", r.ctx.Port, "Send the query to a non-standard port on the server (default 53)")
flags.StringVar(&r.ctx.Resolver, "resolver", r.ctx.Resolver, "Resolver is the hostname or IP address of the name server to use (default empty)")
flags.StringVar(&r.ctx.QueryType, "type", r.ctx.QueryType, "Specifies the type of DNS query to perform (default \"A\")")
flags.BoolVar(&r.ctx.Trace, "trace", r.ctx.Trace, "Toggle tracing of the delegation path from the root name servers (default false)")

r.Cmd.AddCommand(dnsCmd)
}
Expand All @@ -68,6 +69,7 @@ func (r *Root) RunDNS(cmd *cobra.Command, args []string) error {
return err
}

defer r.UpdateHistory()
r.ctx.RecordToSession = true

opts := &globalping.MeasurementCreate{
Expand Down Expand Up @@ -100,7 +102,12 @@ func (r *Root) RunDNS(cmd *cobra.Command, args []string) error {
}

r.ctx.MeasurementsCreated++

hm := &view.HistoryItem{
Id: res.ID,
Status: globalping.StatusInProgress,
StartedAt: r.time.Now(),
}
r.ctx.History.Push(hm)
if r.ctx.RecordToSession {
r.ctx.RecordToSession = false
err := saveIdToSession(res.ID)
Expand Down
20 changes: 16 additions & 4 deletions cmd/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ func Test_Execute_DNS_Default(t *testing.T) {
viewerMock := mocks.NewMockViewer(ctrl)
viewerMock.EXPECT().Output(measurementID1, expectedOpts).Times(1).Return(nil)

timeMock := mocks.NewMockTime(ctrl)
timeMock.EXPECT().Now().Return(defaultCurrentTime).AnyTimes()

w := new(bytes.Buffer)
printer := view.NewPrinter(nil, w, w)
ctx := createDefaultContext()
root := NewRoot(printer, ctx, viewerMock, nil, gbMock, nil)
ctx := createDefaultContext("dns")
root := NewRoot(printer, ctx, viewerMock, timeMock, gbMock, nil)

os.Args = []string{"globalping", "dns", "jsdelivr.com",
"from", "Berlin",
Expand All @@ -67,6 +70,15 @@ func Test_Execute_DNS_Default(t *testing.T) {

b, err := os.ReadFile(getMeasurementsPath())
assert.NoError(t, err)
expectedHistory := []byte(measurementID1 + "\n")
assert.Equal(t, expectedHistory, b)
expectedHistory := measurementID1 + "\n"
assert.Equal(t, expectedHistory, string(b))

b, err = os.ReadFile(getHistoryPath())
assert.NoError(t, err)
expectedHistory = createDefaultExpectedHistoryLogItem(
"1",
measurementID1,
"dns jsdelivr.com from Berlin --limit 2 --type MX --resolver 1.1.1.1 --port 99 --protocol tcp --trace",
)
assert.Equal(t, expectedHistory, string(b))
}
Loading

0 comments on commit c522c89

Please sign in to comment.