Skip to content

Commit

Permalink
CLI: add descirbe workflow execution (uber#636)
Browse files Browse the repository at this point in the history
* CLI: add descirbe workflow execution

* Change frontend validate runid, make wf desc runid optional

* Pretty output for pendingActivity
  • Loading branch information
vancexu authored Mar 27, 2018
1 parent c444cac commit 3a65572
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 3 deletions.
2 changes: 1 addition & 1 deletion service/frontend/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1897,7 +1897,7 @@ func (wh *WorkflowHandler) validateExecution(w *gen.WorkflowExecution, scope int
if w.WorkflowId == nil || w.GetWorkflowId() == "" {
return wh.error(errWorkflowIDNotSet, scope)
}
if w.RunId != nil && uuid.Parse(*w.RunId) == nil {
if w.GetRunId() != "" && uuid.Parse(w.GetRunId()) == nil {
return wh.error(errInvalidRunID, scope)
}
return nil
Expand Down
14 changes: 13 additions & 1 deletion tools/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,24 @@ User need to run `show` to view workflow history/progress.
# a shortcut of this is (without -w -r flag)
./cadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717 866ae14c-88cf-4f1e-980f-571e031d71b0
# if run_id is not provided, it will show the latest run history for that workflow_id
# if run_id is not provided, it will show the latest run history of that workflow_id
./cadence workflow show -w 3ea6b242-b23c-4279-bb13-f215661b4717
# a shortcut of this is
./cadence workflow showid 3ea6b242-b23c-4279-bb13-f215661b4717
```

- Show workflow execution info
```
./cadence workflow descibe -w 3ea6b242-b23c-4279-bb13-f215661b4717 -r 866ae14c-88cf-4f1e-980f-571e031d71b0
# a shortcut of this is (without -w -r flag)
./cadence workflow descibeid 3ea6b242-b23c-4279-bb13-f215661b4717 866ae14c-88cf-4f1e-980f-571e031d71b0
# if run_id is not provided, it will show the latest workflow execution of that workflow_id
./cadence workflow descibe -w 3ea6b242-b23c-4279-bb13-f215661b4717
# a shortcut of this is
./cadence workflow descibeid 3ea6b242-b23c-4279-bb13-f215661b4717
```

- List closed or open workflow executions
```
./cadence workflow list
Expand Down
111 changes: 110 additions & 1 deletion tools/cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ func showHistoryHelper(c *cli.Context, wid, rid string) {
table.Append([]string{strconv.FormatInt(e.GetEventId(), 10), strconv.FormatInt(e.GetTimestamp(), 10), ColorEvent(e), HistoryEventToString(e)})
} else if printDateTime {
table.Append([]string{strconv.FormatInt(e.GetEventId(), 10), convertTime(e.GetTimestamp(), false), ColorEvent(e), HistoryEventToString(e)})
} else {
} else { // default not show time
table.Append([]string{strconv.FormatInt(e.GetEventId(), 10), ColorEvent(e), HistoryEventToString(e)})
}
}
Expand Down Expand Up @@ -662,6 +662,115 @@ func ListAllWorkflow(c *cli.Context) {
table.Render()
}

// DescribeWorkflow show information about the specified workflow execution
func DescribeWorkflow(c *cli.Context) {
wid := getRequiredOption(c, FlagWorkflowID)
rid := c.String(FlagRunID)

describeWorkflowHelper(c, wid, rid)
}

// DescribeWorkflowWithID show information about the specified workflow execution
func DescribeWorkflowWithID(c *cli.Context) {
if !c.Args().Present() {
ExitIfError(errors.New("workflow_id is required"))
}
wid := c.Args().First()
rid := ""
if c.NArg() >= 2 {
rid = c.Args().Get(1)
}

describeWorkflowHelper(c, wid, rid)
}

func describeWorkflowHelper(c *cli.Context, wid, rid string) {
wfClient := getWorkflowClient(c)

printRawTime := c.Bool(FlagPrintRawTime) // default show datetime instead of raw time

ctx, cancel := newContext()
defer cancel()

resp, err := wfClient.DescribeWorkflowExecution(ctx, wid, rid)
if err != nil {
ErrorAndExit("Describe workflow execution failed", err)
}
var o interface{}
if printRawTime {
o = resp
} else {
o = convertDescribeWorkflowExecutionResponse(resp)
}
prettyPrintJSONObject(o)
}

func prettyPrintJSONObject(o interface{}) {
b, err := json.MarshalIndent(o, "", " ")
if err != nil {
fmt.Printf("Error when try to print pretty: %v\n", err)
fmt.Println(o)
}
os.Stdout.Write(b)
fmt.Println()
}

// describeWorkflowExecutionResponse is used to print datetime instead of print raw time
type describeWorkflowExecutionResponse struct {
ExecutionConfiguration *s.WorkflowExecutionConfiguration
WorkflowExecutionInfo workflowExecutionInfo
PendingActivities []*pendingActivityInfo
}

// workflowExecutionInfo has same fields as shared.WorkflowExecutionInfo, but has datetime instead of raw time
type workflowExecutionInfo struct {
Execution *s.WorkflowExecution
Type *s.WorkflowType
StartTime *string // change from *int64
CloseTime *string // change from *int64
CloseStatus *s.WorkflowExecutionCloseStatus
HistoryLength *int64
}

// pendingActivityInfo has same fields as shared.PendingActivityInfo, but different field type for better display
type pendingActivityInfo struct {
ActivityID *string
ActivityType *s.ActivityType
State *s.PendingActivityState
HeartbeatDetails *string // change from byte[]
LastHeartbeatTimestamp *string // change from *int64
}

func convertDescribeWorkflowExecutionResponse(resp *s.DescribeWorkflowExecutionResponse) *describeWorkflowExecutionResponse {
info := resp.WorkflowExecutionInfo
executionInfo := workflowExecutionInfo{
Execution: info.Execution,
Type: info.Type,
StartTime: common.StringPtr(convertTime(info.GetStartTime(), false)),
CloseTime: common.StringPtr(convertTime(info.GetCloseTime(), false)),
CloseStatus: info.CloseStatus,
HistoryLength: info.HistoryLength,
}
var pendingActs []*pendingActivityInfo
var tmpAct *pendingActivityInfo
for _, pa := range resp.PendingActivities {
tmpAct = &pendingActivityInfo{
ActivityID: pa.ActivityID,
ActivityType: pa.ActivityType,
State: pa.State,
HeartbeatDetails: common.StringPtr(string(pa.HeartbeatDetails)),
LastHeartbeatTimestamp: common.StringPtr(convertTime(pa.GetLastHeartbeatTimestamp(), false)),
}
pendingActs = append(pendingActs, tmpAct)
}

return &describeWorkflowExecutionResponse{
ExecutionConfiguration: resp.ExecutionConfiguration,
WorkflowExecutionInfo: executionInfo,
PendingActivities: pendingActs,
}
}

func createTableForListWorkflow(listAll bool) *tablewriter.Table {
table := tablewriter.NewWriter(os.Stdout)
table.SetBorder(false)
Expand Down
37 changes: 37 additions & 0 deletions tools/cli/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,5 +369,42 @@ func newWorkflowCommands() []cli.Command {
QueryWorkflowUsingStackTrace(c)
},
},
{
Name: "describe",
Aliases: []string{"desc"},
Usage: "show information of workflow execution",
Flags: []cli.Flag{
cli.StringFlag{
Name: FlagWorkflowIDWithAlias,
Usage: "WorkflowID",
},
cli.StringFlag{
Name: FlagRunIDWithAlias,
Usage: "RunID",
},
cli.BoolFlag{
Name: FlagPrintRawTimeWithAlias,
Usage: "Print raw time stamp",
},
},
Action: func(c *cli.Context) {
DescribeWorkflow(c)
},
},
{
Name: "describeid",
Aliases: []string{"descid"},
Usage: "show information of workflow execution with given workflow_id and optional run_id (a shortcut of `describe -w <wid> -r <rid>`)",
Description: "cadence workflow describeid <workflow_id> <run_id>. workflow_id is required; run_id is optional",
Flags: []cli.Flag{
cli.BoolFlag{
Name: FlagPrintRawTimeWithAlias,
Usage: "Print raw time stamp",
},
},
Action: func(c *cli.Context) {
DescribeWorkflowWithID(c)
},
},
}
}

0 comments on commit 3a65572

Please sign in to comment.