Prettify duration in cgr-console. Fixes#432

This commit is contained in:
Tripon Alexandru-Ionut
2019-06-20 12:39:32 +03:00
committed by Dan Christian Bogos
parent 83fe98ada8
commit e994711d73
21 changed files with 224 additions and 9 deletions

View File

@@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
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())

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -38,6 +38,7 @@ type Commander interface {
ClientArgs() []string // for autocompletion
Name() string
LocalExecute() string
GetFormatedResult(result interface{}) string
}
func GetCommands() map[string]Commander {

View File

@@ -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)
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
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)
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -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{}{},
})
}

View File

@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
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{}{},
})
}

View File

@@ -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)
}