diff --git a/config.go b/config.go index f48856d..20efddf 100644 --- a/config.go +++ b/config.go @@ -323,6 +323,7 @@ func HandleConfigChange(jctx *JCtx, config Config, restart *bool) error { jctx.config = config logInit(jctx) internalJtimonLogInit(jctx) + initInternalJtimon(jctx) if restart != nil { jLog(jctx, fmt.Sprintf("Restarting worker process to spawn new device connection for: %s", jctx.file)) *restart = true @@ -348,6 +349,7 @@ func ConfigRead(jctx *JCtx, init bool, restart *bool) error { jctx.config = config logInit(jctx) internalJtimonLogInit(jctx) + initInternalJtimon(jctx) b, err := json.MarshalIndent(jctx.config, "", " ") if err != nil { return fmt.Errorf("config parsing error (json marshal) for %s: %v", jctx.file, err) diff --git a/gnmi_utils.go b/gnmi_utils.go index 6dbf45c..ad32e6f 100644 --- a/gnmi_utils.go +++ b/gnmi_utils.go @@ -2,6 +2,8 @@ package main import ( "bytes" + "encoding/binary" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -72,48 +74,47 @@ type gnmiParseOutputT struct { inKvs uint64 } - // parseKeyValuePairs takes an input string in the format `prefix[key = "value"]` // and returns the prefix as a string and the key-value pairs as a map. // // The input string can contain multiple key-value pairs in the same or different brackets. // The keys and values are trimmed of quotes and spaces. // -// If the input string does not contain any brackets, the function returns the entire string +// If the input string does not contain any brackets, the function returns the entire string // as the prefix and an empty map. func parseKeyValuePairs(input string) (string, map[string]string) { - // Initialize a map to hold the key-value pairs - result := make(map[string]string) + // Initialize a map to hold the key-value pairs + result := make(map[string]string) - // Split the input string by the first occurrence of [" to get the prefix and the rest - parts := strings.SplitN(input, "[", 2) - prefix := parts[0] + // Split the input string by the first occurrence of [" to get the prefix and the rest + parts := strings.SplitN(input, "[", 2) + prefix := parts[0] - // Match anything inside square brackets - re := regexp.MustCompile(`\[(.*?)\]`) - matches := re.FindAllString(input, -1) + // Match anything inside square brackets + re := regexp.MustCompile(`\[(.*?)\]`) + matches := re.FindAllString(input, -1) - for _, match := range matches { - // Remove the square brackets - match = strings.Trim(match, "[]") + for _, match := range matches { + // Remove the square brackets + match = strings.Trim(match, "[]") - // Split by "and" to support multiple key-value pairs in the same brackets - pairs := strings.Split(match, "and") + // Split by "and" to support multiple key-value pairs in the same brackets + pairs := strings.Split(match, "and") - for _, pair := range pairs { - // Split by "=" to separate the key and value - kv := strings.Split(pair, "=") + for _, pair := range pairs { + // Split by "=" to separate the key and value + kv := strings.Split(pair, "=") - // Trim the quotes and spaces from the key and value - key := strings.Trim(kv[0], " \"") - value := strings.Trim(kv[1], " \"") + // Trim the quotes and spaces from the key and value + key := strings.Trim(kv[0], " \"") + value := strings.Trim(kv[1], " \"") - // Add the key-value pair to the result map - result[key] = value - } - } + // Add the key-value pair to the result map + result[key] = value + } + } - return prefix, result + return prefix, result } // Convert xpath to gNMI path @@ -359,7 +360,16 @@ func gnmiParseValue(gnmiValue *gnmi.TypedValue, ts bool, enableUint bool) (inter case *gnmi.TypedValue_BoolVal: value = gnmiValue.GetBoolVal() case *gnmi.TypedValue_BytesVal: - value = gnmiValue.GetBytesVal() + byteVal := gnmiValue.GetBytesVal() + if len(byteVal) == 4 { + var double_val float32 + if err := binary.Read(bytes.NewReader(byteVal), binary.LittleEndian, &double_val); err != nil { + value = hex.EncodeToString(byteVal) + } + value = fmt.Sprintf("%0.2f", double_val) + } else { + value = hex.EncodeToString(byteVal) + } case *gnmi.TypedValue_AsciiVal: value = gnmiValue.GetAsciiVal() case *gnmi.TypedValue_AnyVal: diff --git a/grpc.go b/grpc.go index 7795ba3..a14f0de 100644 --- a/grpc.go +++ b/grpc.go @@ -47,7 +47,7 @@ func getGPRCDialOptions(jctx *JCtx, vendor *vendor) ([]grpc.DialOption, error) { return nil, err } - if *stateHandler { + if *statsHandler { opts = append(opts, grpc.WithStatsHandler(&statshandler{jctx: jctx})) if isCsvStatsEnabled(jctx) { jctx.config.InternalJtimon.csvLogger.Printf(fmt.Sprintf("%s,%s,%s,%s,%s,%s,%s,%s,%s\n", diff --git a/influx.go b/influx.go index 0d9fe40..e16f625 100644 --- a/influx.go +++ b/influx.go @@ -503,6 +503,17 @@ func addIDB(ocData *na_pb.OpenConfigData, jctx *JCtx, rtime time.Time) { value32 := v.GetFloatValue() checkAndCeilFloatValues(&value32, nil, &floatVal) kv[xmlpath] = floatVal + case *na_pb.KeyValue_LeaflistValue: + e := v.GetLeaflistValue().Element + var leafListStr string + for _, elem := range e { + switch elem.Value.(type) { + case *na_pb.TypedValue_LeaflistStrValue: + llStrValue := elem.GetLeaflistStrValue() + leafListStr = leafListStr + llStrValue + "," + } + } + kv[xmlpath] = leafListStr[:len(leafListStr)-1] default: } diff --git a/internal_jtimon.go b/internal_jtimon.go index 3d55ce7..d497350 100644 --- a/internal_jtimon.go +++ b/internal_jtimon.go @@ -3,12 +3,13 @@ package main import ( "encoding/json" "fmt" - gnmi "github.com/Juniper/jtimon/gnmi/gnmi" - na_pb "github.com/Juniper/jtimon/telemetry" "log" "os" "regexp" "strings" + + gnmi "github.com/Juniper/jtimon/gnmi/gnmi" + na_pb "github.com/Juniper/jtimon/telemetry" ) // InternalJtimonConfig type @@ -21,49 +22,61 @@ type InternalJtimonConfig struct { logger *log.Logger preGnmiLogger *log.Logger csvLogger *log.Logger + GnmiEOS bool `json:"gnmi-eos"` + PreGnmiEOS bool `json:"pre-gnmi-eos"` } -func internalJtimonLogInit(jctx *JCtx) { - if jctx.config.InternalJtimon.DataLog == "" { - return +func initInternalJtimon(jctx *JCtx) { + // if Internal Jtimon EOS value is not set, + // then take the EOS value from parent config + if !jctx.config.InternalJtimon.GnmiEOS { + jctx.config.InternalJtimon.GnmiEOS = jctx.config.EOS } - var out *os.File - - var err error - // Gnmi - out, err = os.OpenFile(jctx.config.InternalJtimon.DataLog, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) - if err != nil { - log.Printf("Could not create internal jtimon log file(%s): %v\n", jctx.config.InternalJtimon.DataLog, err) + if !jctx.config.InternalJtimon.PreGnmiEOS { + jctx.config.InternalJtimon.PreGnmiEOS = jctx.config.EOS } +} + +func internalJtimonLogInit(jctx *JCtx) { + if jctx.config.InternalJtimon.DataLog != "" { + var out *os.File - if out != nil { - flags := 0 + var err error + // Gnmi + out, err = os.OpenFile(jctx.config.InternalJtimon.DataLog, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) + if err != nil { + log.Printf("Could not create internal jtimon log file(%s): %v\n", jctx.config.InternalJtimon.DataLog, err) + } - jctx.config.InternalJtimon.logger = log.New(out, "", flags) - jctx.config.InternalJtimon.out = out + if out != nil { + flags := 0 - log.Printf("logging in %s for %s:%d [in the format of internal jtimon tool]\n", - jctx.config.InternalJtimon.DataLog, jctx.config.Host, jctx.config.Port) - } + jctx.config.InternalJtimon.logger = log.New(out, "", flags) + jctx.config.InternalJtimon.out = out - // Pre-gnmi - var outPreGnmi *os.File - outPreGnmi, err = os.OpenFile(fmt.Sprintf("%s_pre-gnmi", jctx.config.InternalJtimon.DataLog), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) - if err != nil { - log.Printf("Could not create internal jtimon log file(%s_pre-gnmi): %v\n", jctx.config.InternalJtimon.DataLog, err) - } + log.Printf("logging in %s for %s:%d [in the format of internal jtimon tool]\n", + jctx.config.InternalJtimon.DataLog, jctx.config.Host, jctx.config.Port) + } - if outPreGnmi != nil { - flags := 0 + // Pre-gnmi + var outPreGnmi *os.File + outPreGnmi, err = os.OpenFile(fmt.Sprintf("%s_pre-gnmi", jctx.config.InternalJtimon.DataLog), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600) + if err != nil { + log.Printf("Could not create internal jtimon log file(%s_pre-gnmi): %v\n", jctx.config.InternalJtimon.DataLog, err) + } + + if outPreGnmi != nil { + flags := 0 - jctx.config.InternalJtimon.preGnmiLogger = log.New(outPreGnmi, "", flags) - jctx.config.InternalJtimon.preGnmiOut = outPreGnmi + jctx.config.InternalJtimon.preGnmiLogger = log.New(outPreGnmi, "", flags) + jctx.config.InternalJtimon.preGnmiOut = outPreGnmi - log.Printf("logging in %s_pre-gnmi for %s:%d [in the format of internal jtimon tool]\n", - jctx.config.InternalJtimon.DataLog, jctx.config.Host, jctx.config.Port) + log.Printf("logging in %s_pre-gnmi for %s:%d [in the format of internal jtimon tool]\n", + jctx.config.InternalJtimon.DataLog, jctx.config.Host, jctx.config.Port) + } } - if *stateHandler && jctx.config.InternalJtimon.CsvLog != "" { + if *statsHandler && jctx.config.InternalJtimon.CsvLog != "" { csvStatsLogInit(jctx) } } @@ -79,7 +92,7 @@ func internalJtimonLogStop(jctx *JCtx) { jctx.config.InternalJtimon.preGnmiOut = nil jctx.config.InternalJtimon.preGnmiLogger = nil } - if *stateHandler && jctx.config.InternalJtimon.CsvLog != "" { + if *statsHandler && jctx.config.InternalJtimon.CsvLog != "" { csvStatsLogStop(jctx) } } @@ -88,23 +101,33 @@ func isInternalJtimonLogging(jctx *JCtx) bool { return jctx.config.InternalJtimon.logger != nil } +func getPath(prefixPath string, pathElements []*gnmi.PathElem) string { + for _, pe := range pathElements { + peName := pe.GetName() + prefixPath += gXPathTokenPathSep + peName + is_key := false + for k, v := range pe.GetKey() { + if is_key { + prefixPath += " and " + k + "='" + v + "'" + } else { + prefixPath += "[" + k + "='" + v + "'" + is_key = true + } + } + if is_key { + prefixPath += "]" + } + } + + return prefixPath +} + func jLogInternalJtimonForGnmi(jctx *JCtx, parseOutput *gnmiParseOutputT, rsp *gnmi.SubscribeResponse) { - if jctx.config.InternalJtimon.logger == nil { + if jctx.config.InternalJtimon.logger == nil || parseOutput.jHeader == nil || jctx.config.InternalJtimon.DataLog == "" { return } - // Log here in the format of internal jtimon - //var ( - // jxpaths map[string]interface{} - // jGnmiHdr string - //) - - s := "" - //if parseOutput.jHeader.hdr != nil { - // s += fmt.Sprintf("system_id: %s\n", parseOutput.jHeader.hdr.String()) - //} else { - // s += fmt.Sprintf("system_id: %s\n", parseOutput.jHeader.hdrExt.String()) - //} + s := "" // Keep the original string format var jHeaderData map[string]interface{} jGnmiHdrExt, err := json.Marshal(parseOutput.jHeader.hdrExt) if err != nil { @@ -117,6 +140,9 @@ func jLogInternalJtimonForGnmi(jctx *JCtx, parseOutput *gnmiParseOutputT, rsp *g return } + // Prepare outputData for JSON format + outputData := make(map[string]interface{}) // Map to hold the JSON output + outJHeaderKeys := []string{ "system_id", "component_id", @@ -127,6 +153,7 @@ func jLogInternalJtimonForGnmi(jctx *JCtx, parseOutput *gnmiParseOutputT, rsp *g "sequence_number", "export_timestamp", } + for _, v := range outJHeaderKeys { if _, ok := jHeaderData[v]; ok { strVal := convertToString(jHeaderData[v]) @@ -135,13 +162,17 @@ func jLogInternalJtimonForGnmi(jctx *JCtx, parseOutput *gnmiParseOutputT, rsp *g "to Streamed path. Unable to convert extension value: %v to string. ", v, jHeaderData[v])) continue } + // Add to plain string format s += fmt.Sprintf("%s: %s\n", v, strVal) + + // Add to JSON structure + outputData[v] = strVal } } notif := rsp.GetUpdate() if notif != nil { - // Form an xpath for prefix here, as the internal jtimon tool does it this way. + // Plain text formatting prefixPath := "" if !jctx.config.Vendor.RemoveNS { prefixPath = notif.Prefix.GetOrigin() @@ -152,56 +183,79 @@ func jLogInternalJtimonForGnmi(jctx *JCtx, parseOutput *gnmiParseOutputT, rsp *g prefix := notif.GetPrefix() if prefix != nil { - for _, pe := range prefix.GetElem() { - peName := pe.GetName() - prefixPath += gXPathTokenPathSep + peName - is_key := false - for k, v := range pe.GetKey() { - if is_key { - prefixPath += " and " + k + "='" + v + "'" - } else { - prefixPath += "[" + k + "='" + v + "'" - is_key = true - } - } - if is_key { - prefixPath += "]" - } - } + prefixPath = getPath(prefixPath, prefix.GetElem()) } s += fmt.Sprintf( "Update {\n\ttimestamp: %d\n\tprefix: %v\n", notif.GetTimestamp(), prefixPath) - // Parse all the updates here + // Create a map to hold notification data for JSON output + notifData := make(map[string]interface{}) + notifData["timestamp"] = notif.GetTimestamp() + notifData["prefix"] = prefixPath + + // Parse delete paths (both for string and JSON) + var delPaths []string + for _, d := range notif.Delete { + delPath := getPath(prefixPath, d.GetElem()) + s += fmt.Sprintf("del_path: %s\n", delPath) + delPaths = append(delPaths, delPath) + } + notifData["del_paths"] = delPaths + + // Parse updates (both for string and JSON) + var updates []map[string]interface{} for _, u := range notif.Update { - notifString := u.String() s += fmt.Sprintf("Update {\n\tpath {\n") + + update := make(map[string]interface{}) + re := regexp.MustCompile(`name:\"(.*?)\"`) matches := re.FindAllStringSubmatch(u.String(), -1) + var elems []string for _, match := range matches { - s += fmt.Sprintf("\t\telem {\n\t\t\t") - s += fmt.Sprintf("name: %s\n\t\t}\n", match[1]) + s += fmt.Sprintf("\t\telem {\n\t\t\tname: %s\n\t\t}\n", match[1]) + elems = append(elems, match[1]) } + update["elems"] = elems - // Define regular expression pattern to match "key:val" + // Extract key-value pairs for the update + notifString := u.String() re = regexp.MustCompile(`val:\{(.*?)\}`) result := re.FindStringSubmatch(notifString) if len(result) > 1 { keyVal := strings.Split(result[1], ":") - s += fmt.Sprintf("\t\tval {\n\t\t\t") - s += fmt.Sprintf("%s: %s\n\t\t}\n", keyVal[0], keyVal[1]) + s += fmt.Sprintf("\t\tval {\n\t\t\t%s: %s\n\t\t}\n", keyVal[0], keyVal[1]) + update["key"] = keyVal[0] + update["value"] = strings.Trim(keyVal[1], "\"") } + updates = append(updates, update) s += fmt.Sprintf("\t}\n") } s += fmt.Sprintf("}\n") + notifData["updates"] = updates // Add update data to JSON output + + outputData["notification"] = notifData // Add notification to JSON output } - jctx.config.InternalJtimon.logger.Printf(s) + + if *outJSON { + // Marshal the JSON data and print it + jsonOutput, err := json.MarshalIndent(outputData, "", " ") + if err != nil { + jLog(jctx, "Error marshaling output to JSON") + return + } + jctx.config.InternalJtimon.logger.Printf("%s\n", jsonOutput) + } else { + // Print the plain text output + jctx.config.InternalJtimon.logger.Print(s) + } + } func jLogInternalJtimonForPreGnmi(jctx *JCtx, ocdata *na_pb.OpenConfigData, outString string) { - if jctx.config.InternalJtimon.logger == nil { + if jctx.config.InternalJtimon.logger == nil || jctx.config.InternalJtimon.DataLog == "" { return } diff --git a/jtisim/gnmi_utils.go b/jtisim/gnmi_utils.go index 0301bce..91f7b1b 100644 --- a/jtisim/gnmi_utils.go +++ b/jtisim/gnmi_utils.go @@ -2,19 +2,21 @@ package jtisim import ( "bytes" + "encoding/binary" + "encoding/hex" "encoding/json" "errors" "fmt" "math" "strings" - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/ptypes" - google_protobuf "github.com/golang/protobuf/ptypes/any" gnmi "github.com/Juniper/jtimon/gnmi/gnmi" gnmi_ext1 "github.com/Juniper/jtimon/gnmi/gnmi_ext" gnmi_juniper_header "github.com/Juniper/jtimon/gnmi/gnmi_juniper_header" gnmi_juniper_header_ext "github.com/Juniper/jtimon/gnmi/gnmi_juniper_header_ext" + "github.com/golang/protobuf/proto" + "github.com/golang/protobuf/ptypes" + google_protobuf "github.com/golang/protobuf/ptypes/any" ) const ( @@ -300,7 +302,16 @@ func gnmiParseValue(gnmiValue *gnmi.TypedValue, ts bool) (interface{}, error) { case *gnmi.TypedValue_BoolVal: value = gnmiValue.GetBoolVal() case *gnmi.TypedValue_BytesVal: - value = gnmiValue.GetBytesVal() + byteVal := gnmiValue.GetBytesVal() + if len(byteVal) == 4 { + var double_val float32 + if err := binary.Read(bytes.NewReader(byteVal), binary.LittleEndian, &double_val); err != nil { + value = hex.EncodeToString(byteVal) + } + value = fmt.Sprintf("%0.2f", double_val) + } else { + value = hex.EncodeToString(byteVal) + } case *gnmi.TypedValue_AsciiVal: value = gnmiValue.GetAsciiVal() case *gnmi.TypedValue_AnyVal: diff --git a/main.go b/main.go index 9f6a11d..44655bc 100644 --- a/main.go +++ b/main.go @@ -17,7 +17,7 @@ var ( outJSON = flag.Bool("json", false, "Convert telemetry packet into JSON") logMux = flag.Bool("log-mux-stdout", false, "All logs to stdout") maxRun = flag.Int64("max-run", 0, "Max run time in seconds") - stateHandler = flag.Bool("stats-handler", false, "Use GRPC statshandler") + statsHandler = flag.Bool("stats-handler", false, "Use GRPC statshandler") versionOnly = flag.Bool("version", false, "Print version and build-time of the binary and exit") compression = flag.String("compression", "", "Enable HTTP/2 compression (gzip)") prom = flag.Bool("prometheus", false, "Stats for prometheus monitoring system") diff --git a/multi_vendor.go b/multi_vendor.go index 0949f38..2aa5918 100644 --- a/multi_vendor.go +++ b/multi_vendor.go @@ -84,12 +84,16 @@ func subscribePrePostGNMI(conn *grpc.ClientConn, jctx *JCtx, cfg Config, paths [ // Launch goroutines for each subscription function go func() { gnmiPaths := getGnmiPaths(cfg) - gnmiResultCh <- subscribegNMI(conn, jctx, cfg, gnmiPaths) + if len(gnmiPaths) > 0 { + gnmiResultCh <- subscribegNMI(conn, jctx, cfg, gnmiPaths) + } }() go func() { preGnmiPaths := getPreGnmiPaths(cfg) - junosResultCh <- subscribeJunos(conn, jctx, cfg, preGnmiPaths) + if len(preGnmiPaths) > 0 { + junosResultCh <- subscribeJunos(conn, jctx, cfg, preGnmiPaths) + } }() // Use select to wait for the first result to be available diff --git a/statshandler.go b/statshandler.go index 5784b55..d29a0ca 100644 --- a/statshandler.go +++ b/statshandler.go @@ -2,13 +2,14 @@ package main import ( "fmt" - gnmi_ext1 "github.com/Juniper/jtimon/gnmi/gnmi_ext" - gnmi_juniper_header_ext "github.com/Juniper/jtimon/gnmi/gnmi_juniper_header_ext" "log" "os" "sync" "time" + gnmi_ext1 "github.com/Juniper/jtimon/gnmi/gnmi_ext" + gnmi_juniper_header_ext "github.com/Juniper/jtimon/gnmi/gnmi_juniper_header_ext" + gnmi_pb "github.com/Juniper/jtimon/gnmi/gnmi" na_pb "github.com/Juniper/jtimon/telemetry" proto "github.com/golang/protobuf/proto" @@ -72,7 +73,7 @@ func (h *statshandler) HandleRPC(ctx context.Context, s stats.RPCStats) { case *stats.InPayload: h.jctx.stats.totalInPayloadLength += uint64(s.(*stats.InPayload).Length) h.jctx.stats.totalInPayloadWireLength += uint64(s.(*stats.InPayload).WireLength) - if *stateHandler && h.jctx.config.InternalJtimon.CsvLog != "" { + if *statsHandler && h.jctx.config.InternalJtimon.CsvLog != "" { switch v := (s.(*stats.InPayload).Payload).(type) { case *na_pb.OpenConfigData: updateStats(h.jctx, v, false) @@ -178,7 +179,7 @@ func (h *statshandler) getKPIStats(subResponse *gnmi_pb.SubscribeResponse) *kpiS } func updateStats(jctx *JCtx, ocData *na_pb.OpenConfigData, needLock bool) { - if !*stateHandler { + if !*statsHandler { return } if needLock { @@ -189,7 +190,7 @@ func updateStats(jctx *JCtx, ocData *na_pb.OpenConfigData, needLock bool) { } func updateStatsKV(jctx *JCtx, needLock bool, count uint64) { - if !*stateHandler { + if !*statsHandler { return } @@ -201,7 +202,7 @@ func updateStatsKV(jctx *JCtx, needLock bool, count uint64) { } func periodicStats(jctx *JCtx) { - if !*stateHandler { + if !*statsHandler { return } pstats := jctx.config.Log.PeriodicStats @@ -245,7 +246,7 @@ func periodicStats(jctx *JCtx) { } func printSummary(jctx *JCtx) { - if !*stateHandler { + if !*statsHandler { return } @@ -264,17 +265,22 @@ func printSummary(jctx *JCtx) { s += fmt.Sprintf("\n") jLog(jctx, fmt.Sprintf("\n%s\n", s)) + + // Print Summary to terminal for internal Jitmon + if jctx.config.InternalJtimon.CsvLog != "" { + fmt.Println(s) + } } func isCsvStatsEnabled(jctx *JCtx) bool { - if *stateHandler && jctx.config.InternalJtimon.CsvLog != "" { + if *statsHandler && jctx.config.InternalJtimon.CsvLog != "" { return true } return false } func csvStatsLogInit(jctx *JCtx) { - if !*stateHandler && jctx.config.InternalJtimon.CsvLog == "" { + if !*statsHandler && jctx.config.InternalJtimon.CsvLog == "" { return } var out *os.File diff --git a/subscribe_gnmi.go b/subscribe_gnmi.go index 3c9fe7f..3c5b144 100644 --- a/subscribe_gnmi.go +++ b/subscribe_gnmi.go @@ -99,7 +99,7 @@ func publishToPrometheus(jctx *JCtx, parseOutput *gnmiParseOutputT) { } /* - * Publish parsed output to Influx. Make sure there are only inegers, + * Publish parsed output to Influx. Make sure there are only integers, * floats and strings. Influx Line Protocol doesn't support other types */ func publishToInflux(jctx *JCtx, mName string, prefixPath string, kvpairs map[string]string, xpaths map[string]interface{}) error { @@ -107,6 +107,15 @@ func publishToInflux(jctx *JCtx, mName string, prefixPath string, kvpairs map[st return nil } + // Convert leaf-list values if present in xpaths for influxdb Point write + for key, value := range xpaths { + // Check if the value is a slice + if members, ok := value.([]string); ok { + // Join the slice elements into a single string separated by commas + xpaths[key] = strings.Join(members, ",") + } + } + pt, err := client.NewPoint(mName, kvpairs, xpaths, time.Now()) if err != nil { msg := fmt.Sprintf("New point creation failed for (key: %v, xpaths: %v): %v", kvpairs, xpaths, err) @@ -291,7 +300,8 @@ func gnmiHandleResponse(jctx *JCtx, rsp *gnmi.SubscribeResponse) error { parseOutput = &tmpParseOp err error - hostname = jctx.config.Host + ":" + strconv.Itoa(jctx.config.Port) + eosEnabled = false + hostname = jctx.config.Host + ":" + strconv.Itoa(jctx.config.Port) ) // Update packet stats @@ -316,7 +326,11 @@ func gnmiHandleResponse(jctx *JCtx, rsp *gnmi.SubscribeResponse) error { updateStatsKV(jctx, true, parseOutput.inKvs) // Ignore all packets till sync response is received. - if !jctx.config.EOS { + eosEnabled = jctx.config.EOS + if isInternalJtimonLogging(jctx) { + eosEnabled = jctx.config.InternalJtimon.GnmiEOS + } + if !eosEnabled { if !jctx.receivedSyncRsp { if parseOutput.jHeader != nil { // For juniper packets, ignore only the packets which are numbered in initial sync sequence range diff --git a/subscribe_juniper_junos.go b/subscribe_juniper_junos.go index 4357224..e20969d 100644 --- a/subscribe_juniper_junos.go +++ b/subscribe_juniper_junos.go @@ -32,61 +32,103 @@ const ( func handleOnePacket(ocData *na_pb.OpenConfigData, jctx *JCtx) { updateStats(jctx, ocData, true) + // Struct to hold the data for JSON output + logData := make(map[string]interface{}) + + // String format logging s := "" if *print || (IsVerboseLogging(jctx) && !*print) || (isInternalJtimonLogging(jctx)) { - s += fmt.Sprintf("system_id: %s\n", ocData.SystemId) - s += fmt.Sprintf("component_id: %d\n", ocData.ComponentId) - s += fmt.Sprintf("sub_component_id: %d\n", ocData.SubComponentId) - s += fmt.Sprintf("path: %s\n", ocData.Path) - s += fmt.Sprintf("sequence_number: %d\n", ocData.SequenceNumber) - s += fmt.Sprintf("timestamp: %d\n", ocData.Timestamp) - s += fmt.Sprintf("sync_response: %v\n", ocData.SyncResponse) - if ocData.SyncResponse { + // Add data to both the string and map + systemId := ocData.SystemId + componentId := ocData.ComponentId + subComponentId := ocData.SubComponentId + path := ocData.Path + sequenceNumber := ocData.SequenceNumber + timestamp := ocData.Timestamp + syncResponse := ocData.SyncResponse + + // String logging + s += fmt.Sprintf("system_id: %s\n", systemId) + s += fmt.Sprintf("component_id: %d\n", componentId) + s += fmt.Sprintf("sub_component_id: %d\n", subComponentId) + s += fmt.Sprintf("path: %s\n", path) + s += fmt.Sprintf("sequence_number: %d\n", sequenceNumber) + s += fmt.Sprintf("timestamp: %d\n", timestamp) + s += fmt.Sprintf("sync_response: %v\n", syncResponse) + if syncResponse { s += "Received sync_response\n" } + // Add data to map for JSON + logData["system_id"] = systemId + logData["component_id"] = componentId + logData["sub_component_id"] = subComponentId + logData["path"] = path + logData["sequence_number"] = sequenceNumber + logData["timestamp"] = timestamp + logData["sync_response"] = syncResponse + del := ocData.GetDelete() + deletePaths := []string{} for _, d := range del { - s += fmt.Sprintf("Delete: %s\n", d.GetPath()) + path := d.GetPath() + s += fmt.Sprintf("Delete: %s\n", path) + deletePaths = append(deletePaths, path) } + logData["delete_paths"] = deletePaths } prefixSeen := false + kvData := []map[string]interface{}{} + for _, kv := range ocData.Kv { updateStatsKV(jctx, true, 1) + kvItem := make(map[string]interface{}) + kvItem["key"] = kv.Key + if *print || (IsVerboseLogging(jctx) && !*print) || (isInternalJtimonLogging(jctx)) { s += fmt.Sprintf(" key: %s\n", kv.Key) switch value := kv.Value.(type) { case *na_pb.KeyValue_DoubleValue: s += fmt.Sprintf(" double_value: %v\n", value.DoubleValue) + kvItem["double_value"] = value.DoubleValue case *na_pb.KeyValue_IntValue: s += fmt.Sprintf(" int_value: %d\n", value.IntValue) + kvItem["int_value"] = value.IntValue case *na_pb.KeyValue_UintValue: s += fmt.Sprintf(" uint_value: %d\n", value.UintValue) + kvItem["uint_value"] = value.UintValue case *na_pb.KeyValue_SintValue: s += fmt.Sprintf(" sint_value: %d\n", value.SintValue) + kvItem["sint_value"] = value.SintValue case *na_pb.KeyValue_BoolValue: s += fmt.Sprintf(" bool_value: %v\n", value.BoolValue) + kvItem["bool_value"] = value.BoolValue case *na_pb.KeyValue_StrValue: s += fmt.Sprintf(" str_value: %s\n", value.StrValue) + kvItem["str_value"] = value.StrValue case *na_pb.KeyValue_BytesValue: s += fmt.Sprintf(" bytes_value: %s\n", value.BytesValue) + kvItem["bytes_value"] = value.BytesValue case *na_pb.KeyValue_LeaflistValue: s += fmt.Sprintf(" leaf_list_value: %s\n", value.LeaflistValue) e := kv.GetLeaflistValue().Element + elements := []string{} for _, elem := range e { - switch elem.Value.(type) { - case *na_pb.TypedValue_LeaflistStrValue: - llStrValue := elem.GetLeaflistStrValue() + if llStrValue := elem.GetLeaflistStrValue(); llStrValue != "" { s += fmt.Sprintf(" leaf_list_value(element): %s\n", llStrValue) + elements = append(elements, llStrValue) } } - + kvItem["leaf_list_elements"] = elements default: s += fmt.Sprintf(" default: %v\n", value) + kvItem["default"] = value } + + kvData = append(kvData, kvItem) } if kv.Key == "__prefix__" { @@ -100,12 +142,26 @@ func handleOnePacket(ocData *na_pb.OpenConfigData, jctx *JCtx) { } } - if s != "" && isInternalJtimonLogging(jctx) { - jLogInternalJtimonForPreGnmi(jctx, nil, s) - } + logData["kv"] = kvData + if s != "" && (*print || (IsVerboseLogging(jctx) && !*print)) { jLog(jctx, s) } + + if isInternalJtimonLogging(jctx) { + if *outJSON { + jsonOutput, err := json.MarshalIndent(logData, "", " ") + if err != nil { + jLog(jctx, fmt.Sprintf("Error marshaling to JSON: %v", err)) + return + } + jLogInternalJtimonForPreGnmi(jctx, nil, string(jsonOutput)) + } else { + if s != "" { + jLogInternalJtimonForPreGnmi(jctx, nil, s) + } + } + } } // subSendAndReceive handles the following @@ -175,7 +231,7 @@ func subSendAndReceive(conn *grpc.ClientConn, jctx *JCtx, } } - if *print || *stateHandler || IsVerboseLogging(jctx) || isInternalJtimonLogging(jctx) { + if *print || *statsHandler || IsVerboseLogging(jctx) || isInternalJtimonLogging(jctx) { handleOnePacket(ocData, jctx) } @@ -237,6 +293,10 @@ func subscribeJunos(conn *grpc.ClientConn, jctx *JCtx, cfg Config, paths []Paths subReqM.PathList = append(subReqM.PathList, &pathM) } additionalConfigM.NeedEos = jctx.config.EOS + // Override EOS if InternalJtimon is configured + if isInternalJtimonLogging(jctx) { + additionalConfigM.NeedEos = jctx.config.InternalJtimon.PreGnmiEOS + } subReqM.AdditionalConfig = &additionalConfigM return subSendAndReceive(conn, jctx, subReqM) diff --git a/subscribe_juniper_junos_test.go b/subscribe_juniper_junos_test.go index a8a03bf..35f4790 100644 --- a/subscribe_juniper_junos_test.go +++ b/subscribe_juniper_junos_test.go @@ -17,7 +17,7 @@ import ( func TestJTISIMSigHup(t *testing.T) { flag.Parse() *noppgoroutines = true - *stateHandler = true + *statsHandler = true *prefixCheck = true config := "tests/data/juniper-junos/config/jtisim-interfaces-file-list-sig.json" @@ -152,7 +152,7 @@ func TestJTISIMSigHup(t *testing.T) { func TestJTISIMSigHupChanged(t *testing.T) { flag.Parse() *noppgoroutines = true - *stateHandler = true + *statsHandler = true *prefixCheck = true config := "tests/data/juniper-junos/config/jtisim-interfaces-file-list-sig.json" @@ -284,7 +284,7 @@ func TestJTISIMSigHupChanged(t *testing.T) { func TestJTISIMSigInt(t *testing.T) { flag.Parse() *noppgoroutines = true - *stateHandler = true + *statsHandler = true *prefixCheck = true config := "tests/data/juniper-junos/config/jtisim-interfaces-file-list-sig.json" @@ -323,7 +323,7 @@ func TestJTISIMSigInt(t *testing.T) { func TestJTISIMRetrySigInt(t *testing.T) { flag.Parse() *noppgoroutines = true - *stateHandler = true + *statsHandler = true *prefixCheck = true config := "tests/data/juniper-junos/config/jtisim-interfaces-file-list-sig-int.json" @@ -385,7 +385,7 @@ func TestPrometheus(t *testing.T) { port := 8090 *noppgoroutines = true - *stateHandler = true + *statsHandler = true *prom = true exporter = promInit() @@ -528,7 +528,7 @@ func TestJTISIMMaxRun(t *testing.T) { t.Run(test.name+test.compression, func(t *testing.T) { flag.Parse() *noppgoroutines = true - *stateHandler = true + *statsHandler = true *prefixCheck = true *compression = test.compression diff --git a/tests/data/cisco-ios-xr/config/xr-all-influx.log b/tests/data/cisco-ios-xr/config/xr-all-influx.log index 09f6d8c..7bdc701 100644 --- a/tests/data/cisco-ios-xr/config/xr-all-influx.log +++ b/tests/data/cisco-ios-xr/config/xr-all-influx.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { diff --git a/tests/data/cisco-ios-xr/config/xr-wdsysmon-influx.log b/tests/data/cisco-ios-xr/config/xr-wdsysmon-influx.log index 6c85db2..889cca6 100644 --- a/tests/data/cisco-ios-xr/config/xr-wdsysmon-influx.log +++ b/tests/data/cisco-ios-xr/config/xr-wdsysmon-influx.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { diff --git a/tests/data/juniper-junos/config/jtisim-influx-alias.log b/tests/data/juniper-junos/config/jtisim-influx-alias.log index 35938f1..823883b 100644 --- a/tests/data/juniper-junos/config/jtisim-influx-alias.log +++ b/tests/data/juniper-junos/config/jtisim-influx-alias.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -91,22 +92,22 @@ Receiving telemetry data from 127.0.0.1:50051 +------------------------------+--------------------+--------------------+--------------------+--------------------+ | Timestamp | KV | Packets | Bytes | Bytes(wire) | +------------------------------+--------------------+--------------------+--------------------+--------------------+ -| Fri May 31 02:22:48 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:46 PDT 2024 | 1980 | 40 | 87418 | 87618 | Batch processing: #packets:40 #points:40 Batch write successful! Post batch write available points: 0 -| Fri May 31 02:22:50 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:48 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:22:52 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:50 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:22:54 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:52 PDT 2024 | 1980 | 40 | 87418 | 87618 | -Collector Stats for 127.0.0.1:50051 (Run time : 8.007675042s) +Collector Stats for 127.0.0.1:50051 (Run time : 8.003061376s) 40 : in-packets 1980 : data points (KV pairs) 25 : in-header wirelength (bytes) diff --git a/tests/data/juniper-junos/config/jtisim-influx.log b/tests/data/juniper-junos/config/jtisim-influx.log index 39b8fb2..a5a88c4 100644 --- a/tests/data/juniper-junos/config/jtisim-influx.log +++ b/tests/data/juniper-junos/config/jtisim-influx.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -92,50 +93,50 @@ Receiving telemetry data from 127.0.0.1:50051 +------------------------------+--------------------+--------------------+--------------------+--------------------+ | Timestamp | KV | Packets | Bytes | Bytes(wire) | +------------------------------+--------------------+--------------------+--------------------+--------------------+ -| Fri May 31 02:22:23 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:21 PDT 2024 | 1980 | 40 | 87418 | 87618 | Batch processing: #packets:40 #points:40 Batch write successful! Post batch write available points: 0 -| Fri May 31 02:22:25 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:23 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:22:27 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:25 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:22:29 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:27 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:22:31 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:29 PDT 2024 | 1980 | 40 | 87418 | 87618 | Batch processing: #packets:40 #points:40 -| Fri May 31 02:22:33 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:07:31 PDT 2024 | 3960 | 80 | 174838 | 175238 | Batch write successful! Post batch write available points: 0 -| Fri May 31 02:22:35 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:07:33 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:22:37 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:07:35 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:22:39 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:07:37 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:22:41 PDT 2024 | 5367 | 109 | 236698 | 237243 | +| Thu Oct 17 12:07:39 PDT 2024 | 3960 | 80 | 174838 | 175238 | Batch processing: #packets:40 #points:40 -| Fri May 31 02:22:43 PDT 2024 | 5940 | 120 | 262258 | 262858 | +| Thu Oct 17 12:07:41 PDT 2024 | 5940 | 120 | 262258 | 262858 | Batch write successful! Post batch write available points: 0 -| Fri May 31 02:22:45 PDT 2024 | 5940 | 120 | 262258 | 262858 | +| Thu Oct 17 12:07:43 PDT 2024 | 5940 | 120 | 262258 | 262858 | -Collector Stats for 127.0.0.1:50051 (Run time : 25.004155208s) +Collector Stats for 127.0.0.1:50051 (Run time : 25.003715882s) 120 : in-packets 5940 : data points (KV pairs) 25 : in-header wirelength (bytes) diff --git a/tests/data/juniper-junos/config/jtisim-interfaces-1.log b/tests/data/juniper-junos/config/jtisim-interfaces-1.log index b25388f..2a69395 100644 --- a/tests/data/juniper-junos/config/jtisim-interfaces-1.log +++ b/tests/data/juniper-junos/config/jtisim-interfaces-1.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -89,44 +90,44 @@ Receiving telemetry data from 127.0.0.1:50051 +------------------------------+--------------------+--------------------+--------------------+--------------------+ | Timestamp | KV | Packets | Bytes | Bytes(wire) | +------------------------------+--------------------+--------------------+--------------------+--------------------+ -| Fri May 31 02:23:21 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:19 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:23 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:21 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:25 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:23 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:27 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:25 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:29 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:27 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:31 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:29 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:33 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:31 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:35 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:33 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:37 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:35 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:39 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:37 PDT 2024 | 4634 | 94 | 204422 | 204892 | -| Fri May 31 02:23:41 PDT 2024 | 5940 | 120 | 262258 | 262858 | +| Thu Oct 17 12:08:39 PDT 2024 | 5940 | 120 | 262258 | 262858 | -| Fri May 31 02:23:43 PDT 2024 | 5940 | 120 | 262258 | 262858 | +| Thu Oct 17 12:08:41 PDT 2024 | 5940 | 120 | 262258 | 262858 | -Collector Stats for 127.0.0.1:50051 (Run time : 25.002534292s) +Collector Stats for 127.0.0.1:50051 (Run time : 25.00183539s) 120 : in-packets 5940 : data points (KV pairs) 25 : in-header wirelength (bytes) diff --git a/tests/data/juniper-junos/config/jtisim-interfaces-2.log b/tests/data/juniper-junos/config/jtisim-interfaces-2.log index 20ec4ac..9254ae1 100644 --- a/tests/data/juniper-junos/config/jtisim-interfaces-2.log +++ b/tests/data/juniper-junos/config/jtisim-interfaces-2.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -82,51 +83,51 @@ New alias creation failed for 127.0.0.1, err: open : no such file or directory compression = none Connecting to 127.0.0.1:50051 gRPC headers from host 127.0.0.1:50051 - content-type: [application/grpc] jtisim: [yes] + content-type: [application/grpc] Receiving telemetry data from 127.0.0.1:50051 +------------------------------+--------------------+--------------------+--------------------+--------------------+ | Timestamp | KV | Packets | Bytes | Bytes(wire) | +------------------------------+--------------------+--------------------+--------------------+--------------------+ -| Fri May 31 02:23:21 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:19 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:23 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:21 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:25 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:23 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:27 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:25 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:29 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:08:27 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:23:31 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:29 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:33 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:31 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:35 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:33 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:37 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:35 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:23:39 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:08:37 PDT 2024 | 4554 | 92 | 201064 | 201524 | -| Fri May 31 02:23:41 PDT 2024 | 5940 | 120 | 262258 | 262858 | +| Thu Oct 17 12:08:39 PDT 2024 | 5940 | 120 | 262258 | 262858 | -| Fri May 31 02:23:43 PDT 2024 | 5940 | 120 | 262258 | 262858 | +| Thu Oct 17 12:08:41 PDT 2024 | 5940 | 120 | 262258 | 262858 | -Collector Stats for 127.0.0.1:50051 (Run time : 25.00119025s) +Collector Stats for 127.0.0.1:50051 (Run time : 25.001281279s) 120 : in-packets 5940 : data points (KV pairs) 25 : in-header wirelength (bytes) diff --git a/tests/data/juniper-junos/config/jtisim-interfaces-3.log b/tests/data/juniper-junos/config/jtisim-interfaces-3.log index b60e621..27b552b 100644 --- a/tests/data/juniper-junos/config/jtisim-interfaces-3.log +++ b/tests/data/juniper-junos/config/jtisim-interfaces-3.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -89,29 +90,29 @@ Receiving telemetry data from 127.0.0.1:50051 +------------------------------+--------------------+--------------------+--------------------+--------------------+ | Timestamp | KV | Packets | Bytes | Bytes(wire) | +------------------------------+--------------------+--------------------+--------------------+--------------------+ -| Fri May 31 02:21:37 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:06:35 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:21:39 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:06:37 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:21:41 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:06:39 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:21:43 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:06:41 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:21:45 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:06:43 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:21:47 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:06:45 PDT 2024 | 3960 | 80 | 174838 | 175238 | -| Fri May 31 02:21:49 PDT 2024 | 3960 | 80 | 174838 | 175238 | +| Thu Oct 17 12:06:47 PDT 2024 | 3960 | 80 | 174838 | 175238 | -Collector Stats for 127.0.0.1:50051 (Run time : 15.001363375s) +Collector Stats for 127.0.0.1:50051 (Run time : 15.001529329s) 80 : in-packets 3960 : data points (KV pairs) 25 : in-header wirelength (bytes) diff --git a/tests/data/juniper-junos/config/jtisim-interfaces-4.log b/tests/data/juniper-junos/config/jtisim-interfaces-4.log index 519110c..92205e6 100644 --- a/tests/data/juniper-junos/config/jtisim-interfaces-4.log +++ b/tests/data/juniper-junos/config/jtisim-interfaces-4.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -86,7 +87,7 @@ compression = none Reconnecting to 127.0.0.1:90052 -Collector Stats for 127.0.0.1:90052 (Run time : 10.004200459s) +Collector Stats for 127.0.0.1:90052 (Run time : 10.001517155s) 0 : in-packets 0 : data points (KV pairs) 0 : in-header wirelength (bytes) diff --git a/tests/data/juniper-junos/config/jtisim-interfaces-6.log b/tests/data/juniper-junos/config/jtisim-interfaces-6.log index 29bf1d0..67f26a9 100644 --- a/tests/data/juniper-junos/config/jtisim-interfaces-6.log +++ b/tests/data/juniper-junos/config/jtisim-interfaces-6.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -89,11 +90,11 @@ Receiving telemetry data from 127.0.0.1:50051 +------------------------------+--------------------+--------------------+--------------------+--------------------+ | Timestamp | KV | Packets | Bytes | Bytes(wire) | +------------------------------+--------------------+--------------------+--------------------+--------------------+ -| Fri May 31 02:21:33 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:06:31 PDT 2024 | 1980 | 40 | 87418 | 87618 | -Collector Stats for 127.0.0.1:50051 (Run time : 3.99416075s) +Collector Stats for 127.0.0.1:50051 (Run time : 3.998590619s) 40 : in-packets 1980 : data points (KV pairs) 25 : in-header wirelength (bytes) diff --git a/tests/data/juniper-junos/config/jtisim-prometheus.log b/tests/data/juniper-junos/config/jtisim-prometheus.log index 358bff4..1a63724 100644 --- a/tests/data/juniper-junos/config/jtisim-prometheus.log +++ b/tests/data/juniper-junos/config/jtisim-prometheus.log @@ -48,7 +48,8 @@ Running config of JTIMON: "internal-jtimon": { "data-log-file": "", "csv-log-file": "", - "csv-stats": false + "gnmi-eos": false, + "pre-gnmi-eos": false }, "paths": [ { @@ -82,21 +83,21 @@ New alias creation failed for 127.0.0.1, err: open : no such file or directory compression = none Connecting to 127.0.0.1:50051 gRPC headers from host 127.0.0.1:50051 - content-type: [application/grpc] jtisim: [yes] + content-type: [application/grpc] Receiving telemetry data from 127.0.0.1:50051 +------------------------------+--------------------+--------------------+--------------------+--------------------+ | Timestamp | KV | Packets | Bytes | Bytes(wire) | +------------------------------+--------------------+--------------------+--------------------+--------------------+ -| Fri May 31 02:22:17 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:15 PDT 2024 | 1980 | 40 | 87418 | 87618 | -| Fri May 31 02:22:19 PDT 2024 | 1980 | 40 | 87418 | 87618 | +| Thu Oct 17 12:07:17 PDT 2024 | 1980 | 40 | 87418 | 87618 | -Collector Stats for 127.0.0.1:50051 (Run time : 6.005650209s) +Collector Stats for 127.0.0.1:50051 (Run time : 6.0011324s) 40 : in-packets 1980 : data points (KV pairs) 25 : in-header wirelength (bytes)