From e994711d735e33109fbf05b35249fd24678990b6 Mon Sep 17 00:00:00 2001 From: Tripon Alexandru-Ionut Date: Thu, 20 Jun 2019 12:39:32 +0300 Subject: [PATCH] Prettify duration in cgr-console. Fixes#432 --- cmd/cgr-console/cgr-console.go | 4 +- console/accounts.go | 6 +++ console/active_sessions.go | 9 ++++ console/attributes_process_event.go | 6 +++ console/chargers_process_event.go | 6 +++ console/command.go | 1 + console/command_executer.go | 74 +++++++++++++++++++++++++++++ console/cost.go | 9 ++++ console/cost_details.go | 9 ++++ console/datacost.go | 9 ++++ console/maxduration.go | 10 ++++ console/passive_sessions.go | 9 ++++ console/resource.go | 6 +++ console/session_initiate.go | 7 +++ console/session_process_event.go | 7 +++ console/session_update.go | 7 +++ console/statqueue.go | 6 +++ console/threshold.go | 6 +++ console/threshold_profile.go | 6 +++ console/triggers.go | 8 +++- utils/reflect.go | 28 +++++++++-- 21 files changed, 224 insertions(+), 9 deletions(-) diff --git a/cmd/cgr-console/cgr-console.go b/cmd/cgr-console/cgr-console.go index 48f23332d..de6468505 100644 --- a/cmd/cgr-console/cgr-console.go +++ b/cmd/cgr-console/cgr-console.go @@ -19,7 +19,6 @@ along with this program. If not, see package main import ( - "encoding/json" "flag" "fmt" "io" @@ -109,8 +108,7 @@ func executeCommand(command string) { if rpcErr := client.Call(cmd.RpcMethod(), param, res); rpcErr != nil { fmt.Println("Error executing command: " + rpcErr.Error()) } else { - result, _ := json.MarshalIndent(res, "", " ") - fmt.Println(string(result)) + fmt.Println(cmd.GetFormatedResult(res)) } } else { fmt.Println(cmd.LocalExecute()) diff --git a/console/accounts.go b/console/accounts.go index 3c4345fae..127559c20 100644 --- a/console/accounts.go +++ b/console/accounts.go @@ -64,3 +64,9 @@ func (self *CmdGetAccounts) RpcResult() interface{} { a := make([]engine.Account, 0) return &a } + +func (self *CmdGetAccounts) GetFormatedResult(result interface{}) string { + return GetFormatedSliceResult(result, map[string]struct{}{ + "MinSleep": struct{}{}, + }) +} diff --git a/console/active_sessions.go b/console/active_sessions.go index 6fce1b8bb..1824cb838 100644 --- a/console/active_sessions.go +++ b/console/active_sessions.go @@ -66,3 +66,12 @@ func (self *CmdActiveSessions) RpcResult() interface{} { var sessions *[]*sessions.ActiveSession return &sessions } + +func (self *CmdActiveSessions) GetFormatedResult(result interface{}) string { + return GetFormatedSliceResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "DurationIndex": struct{}{}, + "MaxRateUnit": struct{}{}, + "DebitInterval": struct{}{}, + }) +} diff --git a/console/attributes_process_event.go b/console/attributes_process_event.go index ef359baa6..721f54a8b 100644 --- a/console/attributes_process_event.go +++ b/console/attributes_process_event.go @@ -68,3 +68,9 @@ func (self *CmdAttributesProcessEvent) RpcResult() interface{} { atr := engine.AttrSProcessEventReply{} return &atr } + +func (self *CmdAttributesProcessEvent) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + }) +} diff --git a/console/chargers_process_event.go b/console/chargers_process_event.go index c6c22df7f..8fb84def1 100644 --- a/console/chargers_process_event.go +++ b/console/chargers_process_event.go @@ -71,3 +71,9 @@ func (self *CmdChargersProcessEvent) RpcResult() interface{} { atr := []*engine.ChrgSProcessEventReply{} return &atr } + +func (self *CmdChargersProcessEvent) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + }) +} diff --git a/console/command.go b/console/command.go index 42aa843d9..85124d3ec 100644 --- a/console/command.go +++ b/console/command.go @@ -38,6 +38,7 @@ type Commander interface { ClientArgs() []string // for autocompletion Name() string LocalExecute() string + GetFormatedResult(result interface{}) string } func GetCommands() map[string]Commander { diff --git a/console/command_executer.go b/console/command_executer.go index 85c77039f..a828d388b 100644 --- a/console/command_executer.go +++ b/console/command_executer.go @@ -134,3 +134,77 @@ func FromJSON(jsn []byte, interestingFields []string) (line string) { } return strings.TrimSpace(line) } + +func getStringValue(v interface{}, defaultDurationFields map[string]struct{}) string { + switch o := v.(type) { + case nil: + return "null" + case int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, + float32, float64: + return fmt.Sprintf(`%v`, o) + case string: + return fmt.Sprintf(`"%s"`, o) + case map[string]interface{}: + return getMapAsString(o, defaultDurationFields) + case []interface{}: + return getSliceAsString(o, defaultDurationFields) + } + return utils.ToJSON(v) +} + +func getSliceAsString(mp []interface{}, defaultDurationFields map[string]struct{}) (out string) { + out = "[" + for _, v := range mp { + out += fmt.Sprintf(`%s,`, getStringValue(v, defaultDurationFields)) + } + return strings.TrimSuffix(out, ",") + "]" +} + +func getMapAsString(mp map[string]interface{}, defaultDurationFields map[string]struct{}) (out string) { + // defaultDurationFields := map[string]struct{}{"b": struct{}{}, "c": struct{}{}, "d": struct{}{}} + out = "{" + for k, v := range mp { + if _, has := defaultDurationFields[k]; has { + if t, err := utils.IfaceAsDuration(v); err == nil { + out += fmt.Sprintf(`"%s":"%s",`, k, t.String()) + continue + } else { + fmt.Println(err) + } + } + out += fmt.Sprintf(`"%s":%s,`, k, getStringValue(v, defaultDurationFields)) + } + return strings.TrimSuffix(out, ",") + "}" +} + +func GetFormatedResult(result interface{}, defaultDurationFields map[string]struct{}) string { + jsonResult, _ := json.Marshal(result) + var mp map[string]interface{} + if err := json.Unmarshal(jsonResult, &mp); err != nil { + out, _ := json.MarshalIndent(result, "", " ") + return string(out) + } + mpstr := getMapAsString(mp, defaultDurationFields) + var out bytes.Buffer + json.Indent(&out, []byte(mpstr), "", " ") + return out.String() +} + +func GetFormatedSliceResult(result interface{}, defaultDurationFields map[string]struct{}) string { + jsonResult, _ := json.Marshal(result) + var mp []interface{} + if err := json.Unmarshal(jsonResult, &mp); err != nil { + out, _ := json.MarshalIndent(result, "", " ") + return string(out) + } + mpstr := getSliceAsString(mp, defaultDurationFields) + var out bytes.Buffer + json.Indent(&out, []byte(mpstr), "", " ") + return out.String() +} + +func (ce *CommandExecuter) GetFormatedResult(result interface{}) string { + out, _ := json.MarshalIndent(result, "", " ") + return string(out) +} diff --git a/console/cost.go b/console/cost.go index ed55754e8..0f5939ac5 100644 --- a/console/cost.go +++ b/console/cost.go @@ -70,3 +70,12 @@ func (self *CmdGetCost) RpcResult() interface{} { func (self *CmdGetCost) ClientArgs() []string { return self.clientArgs } + +func (self *CmdGetCost) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "GroupIntervalStart": struct{}{}, + "RateIncrement": struct{}{}, + "RateUnit": struct{}{}, + }) +} diff --git a/console/cost_details.go b/console/cost_details.go index 1abbb0554..d0070a0c0 100644 --- a/console/cost_details.go +++ b/console/cost_details.go @@ -63,3 +63,12 @@ func (self *CmdGetCostDetails) PostprocessRpcParams() error { func (self *CmdGetCostDetails) RpcResult() interface{} { return &engine.EventCost{} } + +func (self *CmdGetCostDetails) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "GroupIntervalStart": struct{}{}, + "RateIncrement": struct{}{}, + "RateUnit": struct{}{}, + }) +} diff --git a/console/datacost.go b/console/datacost.go index 1638b263b..b4f55bac6 100644 --- a/console/datacost.go +++ b/console/datacost.go @@ -69,3 +69,12 @@ func (self *CmdGetDataCost) RpcResult() interface{} { func (self *CmdGetDataCost) ClientArgs() []string { return self.clientArgs } + +func (self *CmdGetDataCost) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "GroupIntervalStart": struct{}{}, + "RateIncrement": struct{}{}, + "RateUnit": struct{}{}, + }) +} diff --git a/console/maxduration.go b/console/maxduration.go index 02069820b..0fcfebbf0 100644 --- a/console/maxduration.go +++ b/console/maxduration.go @@ -19,6 +19,8 @@ along with this program. If not, see package console import ( + "encoding/json" + "fmt" "time" "github.com/cgrates/cgrates/engine" @@ -74,3 +76,11 @@ func (self *CmdGetMaxDuration) RpcResult() interface{} { func (self *CmdGetMaxDuration) ClientArgs() []string { return self.clientArgs } + +func (self *CmdGetMaxDuration) GetFormatedResult(result interface{}) string { + if tv, canCast := result.(*time.Duration); canCast { + return fmt.Sprintf(`"%s"`, tv.String()) + } + out, _ := json.MarshalIndent(result, "", " ") + return string(out) +} diff --git a/console/passive_sessions.go b/console/passive_sessions.go index 439c0e04c..67dd6995e 100644 --- a/console/passive_sessions.go +++ b/console/passive_sessions.go @@ -65,3 +65,12 @@ func (self *CmdPassiveSessions) RpcResult() interface{} { var sessions *[]*sessions.ActiveSession return &sessions } + +func (self *CmdPassiveSessions) GetFormatedResult(result interface{}) string { + return GetFormatedSliceResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "DurationIndex": struct{}{}, + "MaxRateUnit": struct{}{}, + "DebitInterval": struct{}{}, + }) +} diff --git a/console/resource.go b/console/resource.go index 1e82fdbad..0c4529c53 100644 --- a/console/resource.go +++ b/console/resource.go @@ -64,3 +64,9 @@ func (self *CmdGetResource) RpcResult() interface{} { atr := engine.ResourceProfile{} return &atr } + +func (self *CmdGetResource) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "UsageTTL": struct{}{}, + }) +} diff --git a/console/session_initiate.go b/console/session_initiate.go index eba28d5a5..3592ab183 100644 --- a/console/session_initiate.go +++ b/console/session_initiate.go @@ -68,3 +68,10 @@ func (self *CmdSessionsInitiate) RpcResult() interface{} { var atr *sessions.V1InitSessionReply return &atr } + +func (self *CmdSessionsInitiate) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "MaxUsage": struct{}{}, + }) +} diff --git a/console/session_process_event.go b/console/session_process_event.go index 3826d8678..54b0cf69b 100644 --- a/console/session_process_event.go +++ b/console/session_process_event.go @@ -68,3 +68,10 @@ func (self *CmdSessionsProcessEvent) RpcResult() interface{} { var atr *sessions.V1ProcessEventReply return &atr } + +func (self *CmdSessionsProcessEvent) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "MaxUsage": struct{}{}, + }) +} diff --git a/console/session_update.go b/console/session_update.go index 3548c7850..66e887ec9 100644 --- a/console/session_update.go +++ b/console/session_update.go @@ -68,3 +68,10 @@ func (self *CmdSessionsUpdate) RpcResult() interface{} { var atr *sessions.V1UpdateSessionReply return &atr } + +func (self *CmdSessionsUpdate) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "Usage": struct{}{}, + "MaxUsage": struct{}{}, + }) +} diff --git a/console/statqueue.go b/console/statqueue.go index f49ea929e..d77790e38 100644 --- a/console/statqueue.go +++ b/console/statqueue.go @@ -64,3 +64,9 @@ func (self *CmdGetStatQueue) RpcResult() interface{} { atr := engine.StatQueueProfile{} return &atr } + +func (self *CmdGetStatQueue) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "TTL": struct{}{}, + }) +} diff --git a/console/threshold.go b/console/threshold.go index 3fd6c99f5..8bea54684 100644 --- a/console/threshold.go +++ b/console/threshold.go @@ -66,3 +66,9 @@ func (self *CmdGetThreshold) RpcResult() interface{} { atr := engine.Threshold{} return &atr } + +func (self *CmdGetThreshold) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "MinSleep": struct{}{}, + }) +} diff --git a/console/threshold_profile.go b/console/threshold_profile.go index cae95e017..8d6e55a55 100644 --- a/console/threshold_profile.go +++ b/console/threshold_profile.go @@ -66,3 +66,9 @@ func (self *CmdGetThresholdProfile) RpcResult() interface{} { atr := engine.ThresholdProfile{} return &atr } + +func (self *CmdGetThresholdProfile) GetFormatedResult(result interface{}) string { + return GetFormatedResult(result, map[string]struct{}{ + "MinSleep": struct{}{}, + }) +} diff --git a/console/triggers.go b/console/triggers.go index cf16b8d74..82f652a75 100644 --- a/console/triggers.go +++ b/console/triggers.go @@ -19,7 +19,7 @@ along with this program. If not, see package console import ( - "github.com/cgrates/cgrates/apier/v1" + v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/engine" ) @@ -64,3 +64,9 @@ func (self *CmdGetTriggers) RpcResult() interface{} { atr := engine.ActionTriggers{} return &atr } + +func (self *CmdGetTriggers) GetFormatedResult(result interface{}) string { + return GetFormatedSliceResult(result, map[string]struct{}{ + "MinSleep": struct{}{}, + }) +} diff --git a/utils/reflect.go b/utils/reflect.go index a5f9e09bf..e7497d738 100644 --- a/utils/reflect.go +++ b/utils/reflect.go @@ -128,14 +128,32 @@ func IfaceAsDuration(itm interface{}) (d time.Duration, err error) { switch it := itm.(type) { case time.Duration: return it, nil - case float64: // automatically hitting here also ints + case int: // check every int type + return time.Duration(int64(it)), nil + case int8: + return time.Duration(int64(it)), nil + case int16: + return time.Duration(int64(it)), nil + case int32: return time.Duration(int64(it)), nil case int64: - return time.Duration(it), nil - case int: - return time.Duration(it), nil + return time.Duration(int64(it)), nil + case uint: + return time.Duration(int64(it)), nil + case uint8: + return time.Duration(int64(it)), nil + case uint16: + return time.Duration(int64(it)), nil + case uint32: + return time.Duration(int64(it)), nil + case uint64: + return time.Duration(int64(it)), nil + case float32: // automatically hitting here also ints + return time.Duration(int64(it)), nil + case float64: // automatically hitting here also ints + return time.Duration(int64(it)), nil case string: - return ParseDurationWithNanosecs(itm.(string)) + return ParseDurationWithNanosecs(it) default: err = fmt.Errorf("cannot convert field: %+v to time.Duration", it) }