Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Tokens are stored in your user config directory with strict file permissions (`0
## Core Commands

```bash
rollbaz # default: list active issues for active project
rollbaz # default: list recent active issues for active project
rollbaz active --limit 20
rollbaz recent --limit 20
rollbaz show 274
Expand Down
17 changes: 11 additions & 6 deletions internal/app/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ func (s *Service) Recent(ctx context.Context, limit int, filters IssueFilters) (
return leftTS > rightTS
}

leftOccurrence := uint64Value(items[i].LastOccurrenceID)
rightOccurrence := uint64Value(items[j].LastOccurrenceID)
leftOccurrence := totalOccurrences(items[i])
rightOccurrence := totalOccurrences(items[j])

return leftOccurrence > rightOccurrence
})
Expand Down Expand Up @@ -225,10 +225,7 @@ func matchesTimeFilter(timestamp *uint64, sinceUnix *int64, untilUnix *int64) bo
}

func matchesOccurrenceFilter(item rollbar.Item, minOccurrences *uint64, maxOccurrences *uint64) bool {
occurrences := uint64Value(item.TotalOccurrences)
if occurrences == 0 {
occurrences = uint64Value(item.Occurrences)
}
occurrences := totalOccurrences(item)
if minOccurrences != nil && occurrences < *minOccurrences {
return false
}
Expand Down Expand Up @@ -257,6 +254,14 @@ func mapSummary(item rollbar.Item) IssueSummary {
}
}

func totalOccurrences(item rollbar.Item) uint64 {
if item.TotalOccurrences != nil {
return *item.TotalOccurrences
}

return uint64Value(item.Occurrences)
}

func uint64Value(value *uint64) uint64 {
if value == nil {
return 0
Expand Down
41 changes: 31 additions & 10 deletions internal/app/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,36 @@ func TestServiceActive(t *testing.T) {
}
}

func TestServiceRecentSortsByTimestampThenOccurrence(t *testing.T) {
func TestServiceRecentSortsByTimestamp(t *testing.T) {
t.Parallel()

ts1 := uint64(100)
ts2 := uint64(200)
o1 := uint64(10)
o2 := uint64(20)

service := NewService(fakeAPI{listItems: []rollbar.Item{
{ID: 1, Counter: 1, LastOccurrenceTimestamp: &ts1, LastOccurrenceID: &o1},
{ID: 2, Counter: 2, LastOccurrenceTimestamp: &ts2, LastOccurrenceID: &o2},
{ID: 1, Counter: 1, LastOccurrenceTimestamp: &ts1},
{ID: 2, Counter: 2, LastOccurrenceTimestamp: &ts2},
}})

issues, err := service.Recent(context.Background(), 10, IssueFilters{})
if err != nil {
t.Fatalf("Recent() error = %v", err)
}
if len(issues) < 2 || issues[0].Counter != 2 {
t.Fatalf("unexpected sort order: %+v", issues)
}
}

func TestServiceRecentSortsByTimestampThenTotalOccurrences(t *testing.T) {
t.Parallel()

ts := uint64(100)
totalLow := uint64(10)
totalHigh := uint64(20)

service := NewService(fakeAPI{listItems: []rollbar.Item{
{ID: 1, Counter: 1, LastOccurrenceTimestamp: &ts, TotalOccurrences: &totalLow},
{ID: 2, Counter: 2, LastOccurrenceTimestamp: &ts, TotalOccurrences: &totalHigh},
}})

issues, err := service.Recent(context.Background(), 10, IssueFilters{})
Expand All @@ -95,19 +114,21 @@ func TestServiceRecentSortsByTimestampThenOccurrence(t *testing.T) {
func TestServiceRecentLimitAndOccurrenceFallback(t *testing.T) {
t.Parallel()

o1 := uint64(10)
o2 := uint64(20)
ts := uint64(100)
totalLow := uint64(10)
fallbackHigh := uint64(20)
ignoredOccurrence := uint64(999)

service := NewService(fakeAPI{listItems: []rollbar.Item{
{ID: 1, Counter: 1, LastOccurrenceID: &o1},
{ID: 2, Counter: 2, LastOccurrenceID: &o2},
{ID: 1, Counter: 1, LastOccurrenceTimestamp: &ts, Occurrences: &fallbackHigh},
{ID: 2, Counter: 2, LastOccurrenceTimestamp: &ts, TotalOccurrences: &totalLow, Occurrences: &ignoredOccurrence},
}})

issues, err := service.Recent(context.Background(), 1, IssueFilters{})
if err != nil {
t.Fatalf("Recent() error = %v", err)
}
if len(issues) != 1 || issues[0].Counter != 2 {
if len(issues) != 1 || issues[0].Counter != 1 {
t.Fatalf("unexpected fallback sort/limit: %+v", issues)
}
}
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func NewRootCmd() *cobra.Command {
Short: "Fast Rollbar triage from your terminal",
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
return runActive(cmd.Context(), *flags)
return runRecent(cmd.Context(), *flags)
},
}
cmd.Version = version
Expand Down
10 changes: 5 additions & 5 deletions internal/cli/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,11 @@ func TestProjectRemoveValidation(t *testing.T) {
}
}

func TestRootCommandDefaultRunsActive(t *testing.T) {
func TestRootCommandDefaultRunsRecent(t *testing.T) {
stdout := setupServerAndStdout(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/1/reports/top_active_items":
_, _ = fmt.Fprint(w, `{"err":0,"result":[{"item":{"id":1,"counter":2,"title":"x","status":"active","environment":"production"}}]}`)
case "/api/1/items":
_, _ = fmt.Fprint(w, `{"err":0,"result":{"items":[{"id":1,"counter":3,"title":"y","status":"active","environment":"production"}]}}`)
default:
t.Fatalf("unexpected path: %s", r.URL.Path)
}
Expand All @@ -234,8 +234,8 @@ func TestRootCommandDefaultRunsActive(t *testing.T) {
if err := cmd.Execute(); err != nil {
t.Fatalf("root execute error = %v", err)
}
if !strings.Contains(stdout.String(), "COUNTER") || !strings.Contains(stdout.String(), "x") {
t.Fatalf("expected active list output, got %q", stdout.String())
if !strings.Contains(stdout.String(), "COUNTER") || !strings.Contains(stdout.String(), "y") {
t.Fatalf("expected recent list output, got %q", stdout.String())
}
}

Expand Down