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 @@ -106,7 +106,7 @@ See [docs/COMMANDS.md](docs/COMMANDS.md) for detailed command reference.
| Incidents | ✅ | `incidents list`, `incidents get`, `incidents attachments` | Incident management with attachment support |
| On-Call (Teams) | ✅ | `on-call teams` (CRUD, memberships with roles) | Full team management system with admin/member roles |
| Case Management | ✅ | `cases` (create, search, assign, archive, projects) | Complete case management with priorities P1-P5 |
| Error Tracking | ✅ | `error-tracking issues list`, `error-tracking issues get` | Error issue management |
| Error Tracking | ✅ | `error-tracking issues search`, `error-tracking issues get` | Error issue search and details |
| Service Catalog | ✅ | `service-catalog list`, `service-catalog get` | Service registry management |
| Scorecards | ✅ | `scorecards list`, `scorecards get` | Service quality scores |
| Incident Services/Teams | ❌ | - | Not yet implemented |
Expand Down
172 changes: 141 additions & 31 deletions cmd/error_tracking.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
package cmd

import (
"fmt"

"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
"github.com/DataDog/pup/pkg/formatter"
"github.com/DataDog/pup/pkg/util"
"github.com/spf13/cobra"
)

Expand All @@ -21,14 +21,12 @@ Error tracking automatically groups and prioritizes errors from
your applications to help you identify and fix critical issues.

CAPABILITIES:
• List error issues
• Get error details
• View error trends
• Manage error status
• Search error issues with filtering and sorting
• Get detailed information about a specific issue

EXAMPLES:
# List error issues
pup error-tracking issues list
# Search error issues
pup error-tracking issues search

# Get issue details
pup error-tracking issues get issue-id
Expand All @@ -42,56 +40,168 @@ var errorTrackingIssuesCmd = &cobra.Command{
Short: "Manage error issues",
}

var errorTrackingIssuesListCmd = &cobra.Command{
Use: "list",
Short: "List error issues",
RunE: runErrorTrackingIssuesList,
var errorTrackingIssuesSearchCmd = &cobra.Command{
Use: "search",
Short: "Search error issues",
Long: `Search error tracking issues with optional filtering.

Search for error tracking issues across your applications. Results are sorted
by the specified order (default: total count).

FLAGS:
--query Search query to filter issues (default: "*")
--from Start time: relative (e.g., "1h", "1d", "7d") or absolute
(ISO 8601, Unix timestamp) (default: "1d")
--to End time: "now", relative, or absolute (default: "now")
--order-by Sort order: TOTAL_COUNT, FIRST_SEEN, IMPACTED_SESSIONS,
PRIORITY (default: "TOTAL_COUNT")
--limit Maximum number of issues to return (default: 10)

EXAMPLES:
# Search all issues from the last 24 hours
pup error-tracking issues search

# Search for specific errors
pup error-tracking issues search --query="NullPointerException"

# Search issues from the last 7 days
pup error-tracking issues search --from=7d

# Sort by most recently seen
pup error-tracking issues search --order-by=FIRST_SEEN

# Combine filters
pup error-tracking issues search --query="timeout" --from=3d --order-by=PRIORITY`,
RunE: runErrorTrackingIssuesSearch,
}

var errorTrackingIssuesGetCmd = &cobra.Command{
Use: "get [issue-id]",
Short: "Get issue details",
Args: cobra.ExactArgs(1),
RunE: runErrorTrackingIssuesGet,
Long: `Get detailed information about a specific error tracking issue.

Retrieves full details for an issue including assignee, case, and team owners.

ARGUMENTS:
issue-id The ID of the error tracking issue

EXAMPLES:
# Get issue details
pup error-tracking issues get abc123

# Get issue details as YAML
pup error-tracking issues get abc123 --output=yaml`,
Args: cobra.ExactArgs(1),
RunE: runErrorTrackingIssuesGet,
}

var (
etQuery string
etFrom string
etTo string
etOrderBy string
etLimit int
)

func init() {
errorTrackingIssuesCmd.AddCommand(errorTrackingIssuesListCmd, errorTrackingIssuesGetCmd)
errorTrackingIssuesSearchCmd.Flags().StringVar(&etQuery, "query", "*", "Search query to filter issues")
errorTrackingIssuesSearchCmd.Flags().StringVar(&etFrom, "from", "1d", "Start time (relative or absolute)")
errorTrackingIssuesSearchCmd.Flags().StringVar(&etTo, "to", "now", "End time (relative or absolute)")
errorTrackingIssuesSearchCmd.Flags().StringVar(&etOrderBy, "order-by", "TOTAL_COUNT", "Sort order: TOTAL_COUNT, FIRST_SEEN, IMPACTED_SESSIONS, PRIORITY")
errorTrackingIssuesSearchCmd.Flags().IntVar(&etLimit, "limit", 10, "Maximum number of issues to return")

errorTrackingIssuesCmd.AddCommand(errorTrackingIssuesSearchCmd, errorTrackingIssuesGetCmd)
errorTrackingCmd.AddCommand(errorTrackingIssuesCmd)
}

func runErrorTrackingIssuesList(cmd *cobra.Command, args []string) error {
result := map[string]interface{}{
"data": []map[string]interface{}{},
"meta": map[string]interface{}{
"message": "Error tracking list - API endpoint implementation pending",
func runErrorTrackingIssuesSearch(cmd *cobra.Command, args []string) error {
client, err := getClient()
if err != nil {
return err
}

fromMs, err := util.ParseTimeToUnixMilli(etFrom)
if err != nil {
return err
}

toMs, err := util.ParseTimeToUnixMilli(etTo)
if err != nil {
return err
}

api := datadogV2.NewErrorTrackingApi(client.V2())

orderBy := datadogV2.IssuesSearchRequestDataAttributesOrderBy(etOrderBy)
body := datadogV2.IssuesSearchRequest{
Data: datadogV2.IssuesSearchRequestData{
Attributes: datadogV2.IssuesSearchRequestDataAttributes{
From: fromMs,
To: toMs,
Query: etQuery,
OrderBy: &orderBy,
Persona: datadogV2.ISSUESSEARCHREQUESTDATAATTRIBUTESPERSONA_ALL.Ptr(),
},
Type: datadogV2.ISSUESSEARCHREQUESTDATATYPE_SEARCH_REQUEST,
},
}

output, err := formatter.FormatOutput(result, formatter.OutputFormat(outputFormat))
opts := *datadogV2.NewSearchIssuesOptionalParameters().WithInclude(
[]datadogV2.SearchIssuesIncludeQueryParameterItem{
datadogV2.SEARCHISSUESINCLUDEQUERYPARAMETERITEM_ISSUE,
},
)

resp, r, err := api.SearchIssues(client.Context(), body, opts)
if err != nil {
return formatAPIError("search error tracking issues", err, r)
}

if len(resp.Data) == 0 {
printOutput("No error tracking issues found matching the specified criteria.\n")
return nil
}

if etLimit > 0 && len(resp.Data) > etLimit {
resp.Data = resp.Data[:etLimit]
}

output, err := formatter.FormatOutput(resp, formatter.OutputFormat(outputFormat))
if err != nil {
return err
}
fmt.Println(output)

printOutput("%s\n", output)
return nil
}

func runErrorTrackingIssuesGet(cmd *cobra.Command, args []string) error {
client, err := getClient()
if err != nil {
return err
}

issueID := args[0]
result := map[string]interface{}{
"data": map[string]interface{}{
"id": issueID,
"type": "error_tracking_issue",
"attributes": map[string]interface{}{
"message": "Error tracking details - API endpoint implementation pending",
},
api := datadogV2.NewErrorTrackingApi(client.V2())

opts := *datadogV2.NewGetIssueOptionalParameters().WithInclude(
[]datadogV2.GetIssueIncludeQueryParameterItem{
datadogV2.GETISSUEINCLUDEQUERYPARAMETERITEM_ASSIGNEE,
datadogV2.GETISSUEINCLUDEQUERYPARAMETERITEM_CASE,
datadogV2.GETISSUEINCLUDEQUERYPARAMETERITEM_TEAM_OWNERS,
},
)

resp, r, err := api.GetIssue(client.Context(), issueID, opts)
if err != nil {
return formatAPIError("get error tracking issue", err, r)
}

output, err := formatter.FormatOutput(result, formatter.OutputFormat(outputFormat))
output, err := formatter.FormatOutput(resp, formatter.OutputFormat(outputFormat))
if err != nil {
return err
}
fmt.Println(output)

printOutput("%s\n", output)
return nil
}
47 changes: 38 additions & 9 deletions cmd/error_tracking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func TestErrorTrackingIssuesCmd(t *testing.T) {
commandMap[cmd.Use] = true
}

if !commandMap["list"] {
t.Error("Missing issues list subcommand")
if !commandMap["search"] {
t.Error("Missing issues search subcommand")
}

// Check if get command exists
Expand All @@ -79,24 +79,51 @@ func TestErrorTrackingIssuesCmd(t *testing.T) {
}
}

func TestErrorTrackingIssuesListCmd(t *testing.T) {
if errorTrackingIssuesListCmd == nil {
t.Fatal("errorTrackingIssuesListCmd is nil")
func TestErrorTrackingIssuesSearchCmd(t *testing.T) {
if errorTrackingIssuesSearchCmd == nil {
t.Fatal("errorTrackingIssuesSearchCmd is nil")
}

if errorTrackingIssuesListCmd.Use != "list" {
t.Errorf("Use = %s, want list", errorTrackingIssuesListCmd.Use)
if errorTrackingIssuesSearchCmd.Use != "search" {
t.Errorf("Use = %s, want search", errorTrackingIssuesSearchCmd.Use)
}

if errorTrackingIssuesListCmd.Short == "" {
if errorTrackingIssuesSearchCmd.Short == "" {
t.Error("Short description is empty")
}

if errorTrackingIssuesListCmd.RunE == nil {
if errorTrackingIssuesSearchCmd.RunE == nil {
t.Error("RunE is nil")
}
}

func TestErrorTrackingIssuesSearchCmd_Flags(t *testing.T) {
flags := errorTrackingIssuesSearchCmd.Flags()

tests := []struct {
name string
defaultValue string
}{
{"query", "*"},
{"from", "1d"},
{"to", "now"},
{"order-by", "TOTAL_COUNT"},
{"limit", "10"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := flags.Lookup(tt.name)
if f == nil {
t.Fatalf("Missing --%s flag", tt.name)
}
if f.DefValue != tt.defaultValue {
t.Errorf("--%s default = %q, want %q", tt.name, f.DefValue, tt.defaultValue)
}
})
}
}

func TestErrorTrackingIssuesGetCmd(t *testing.T) {
if errorTrackingIssuesGetCmd == nil {
t.Fatal("errorTrackingIssuesGetCmd is nil")
Expand Down Expand Up @@ -143,3 +170,5 @@ func TestErrorTrackingCmd_CommandHierarchy(t *testing.T) {
}
}
}


4 changes: 2 additions & 2 deletions docs/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pup <domain> <subgroup> <action> [options] # Nested commands
| security | rules, signals, findings (search) | cmd/security.go | ✅ |
| organizations | get, list | cmd/organizations.go | ✅ |
| service-catalog | list, get | cmd/service_catalog.go | ✅ |
| error-tracking | issues (list, get) | cmd/error_tracking.go | ✅ |
| error-tracking | issues (search, get) | cmd/error_tracking.go | ✅ |
| scorecards | list, get | cmd/scorecards.go | ✅ |
| usage | summary, hourly | cmd/usage.go | ✅ |
| apm | services (list, stats, operations, resources), entities (list), dependencies (list), flow-map | cmd/apm.go | ✅ |
Expand Down Expand Up @@ -135,7 +135,7 @@ pup infrastructure hosts list

### Development & Quality
- **cicd** - CI/CD visibility (pipelines, events)
- **error-tracking** - Error management (issues list, issues get)
- **error-tracking** - Error management (issues search, issues get)
- **scorecards** - Service quality (list, get)
- **service-catalog** - Service registry (list, get)

Expand Down