Question about specific table comparison use case

Hi community,

specifically I’m trying to resolve visualization of Routing Tables of Network devices. However, I’m looking for general solution to visualize any table formatted data in specific way. Basically my question is if this is possible with InfluxDB & Grafana and how should I approach to get it done. So please read my explanation and share your ideas.

Prerequisites:
I use gnmic to collect routing table changes via streaming telemetry from network devices. Whenever there is a change in the Network Device routing table it is streamed to gnmic which forwards it to influxdb.

This is example of one routing table change event from the network device as seen by gnmic:

{
  "source": "clab-tellab-xrd-telemetry-rtr1:57400",
  "subscription-name": "default-1710430190",
  "timestamp": 1710430943297000000,
  "time": "2024-03-14T17:42:23.297+02:00",
  "prefix": "Cisco-IOS-XR-ip-rib-ipv4-oper:",
  "updates": [
    {
      "Path": "rib/vrfs/vrf[vrf-name=Mgmt]/afs/af[af-name=IPv4]/safs/saf[saf-name=Unicast]/ip-rib-route-table-names/ip-rib-route-table-name[route-table-name=default]/routes/route[address=1.1.1.1][prefix-length=32]",
      "values": {
        "rib/vrfs/vrf/afs/af/safs/saf/ip-rib-route-table-names/ip-rib-route-table-name/routes/route": {
          "distance": 1,
          "extended-flags": "0",
          "flags": 0,
          "flow-tag": 0,
          "fwd-class": 0,
          "metric": 0,
          "paths-count": 2,
          "priority": 9,
          "protocol-id": 2,
          "protocol-name": "static",
          "qos-group": 255,
          "route-path": {
            "ipv4-rib-edm-path": [
              {
                "address": "172.26.0.1",
                "backup-pathid": 0,
                "binding-label": 1048577,
                "flags": 0,
                "has-labelstk": false,
                "information-source": "0.0.0.0",
                "load-metric": 0,
                "metric": 0,
                "mvpn-present": false,
                "next-hop-afi": 0,
                "next-hop-id": 0,
                "next-hop-safi": 0,
                "next-hop-table-id": 0,
                "num-labels": 0,
                "number-of-extended-communities": 0,
                "pathid": 0,
                "route-label": 1048577,
                "segmented-nexthop-present": false,
                "source-asrt-present": false,
                "source-rd-present": false,
                "tunnel-id": 0,
                "v6-information-source": "::",
                "v6-nexthop": "::",
                "vrf-import-rt-present": false
              },
              {
                "address": "172.26.100.100",
                "backup-pathid": 0,
                "binding-label": 1048577,
                "flags": 0,
                "has-labelstk": false,
                "information-source": "0.0.0.0",
                "load-metric": 0,
                "metric": 0,
                "mvpn-present": false,
                "next-hop-afi": 0,
                "next-hop-id": 0,
                "next-hop-safi": 0,
                "next-hop-table-id": 0,
                "num-labels": 0,
                "number-of-extended-communities": 0,
                "pathid": 0,
                "route-label": 1048577,
                "segmented-nexthop-present": false,
                "source-asrt-present": false,
                "source-rd-present": false,
                "tunnel-id": 0,
                "v6-information-source": "::",
                "v6-nexthop": "::",
                "vrf-import-rt-present": false
              }
            ]
          },
          "route-precedence": 255,
          "route-type": 1,
          "tag": 0
        }
      }
    }
  ]
}

In influxdb it is seen like this (csv export):

#group      false   false  true                            true                            false                    false    true                                                                                                                               true          true        true                                      true           true                 true          true                            true
#datatype   string  long   dateTime:RFC3339                dateTime:RFC3339                dateTime:RFC3339         string   string                                                                                                                             string        string      string                                    string         string               string        string                          string
#default    last
            result  table  _start                           _stop                          _time                    _value   _field                                                                                                                             _measurement  af_af-name  ip-rib-route-table-name_route-table-name  route_address  route_prefix-length  saf_saf-name  source                          vrf_vrf-name
                    0      2024-03-14T07:48:24.986113516Z  2024-03-15T07:48:24.986113516Z  2024-03-14T16:28:00Z     1.1.1.1  Cisco-IOS-XR-ip-rib-ipv4-oper:/rib/vrfs/vrf/afs/af/safs/saf/ip-rib-route-table-names/ip-rib-route-table-name/routes/route/prefix   rib	          IPv4        default                                   1.1.1.1        32                   Unicast       clab-tellab-xrd-telemetry-rtr1  Mgmt

First goal: Single table with latest values in the selected grafana time range
At first I want to have single table. It should not have Time as column anymore but rather collect latest entries of all prefixes in a given time range.

image

So let’s say first prefix (1.1.1.1/32) have multiple events during the time frame with different Nexthop values. Only the latest entry (with nexthops 172.26.0.1, 172.26.100.100) should be present in the table.

Also all of the prefixes (1.1.1.1/32, 2.2.2.2/32 and 4.4.0.0/16) might have events (during the time range) in totally different timestamps.

This way the table presents state of the routing table at the End of the Time range selected.

How this could be achieved?

I see JSON has complex structure and for example Nexthops are under route-path.ipv4-rib-edm-path list in address item. We don’t have to solve all at once. So you can assume everthing is in the same table in the influxdb.

Second goal: Compare same table at two different points in time

Let’s say this is the state of the Table at 30 minutes ago:
image

And this is the same table now (30 minutes later):
Screenshot from 2024-03-15 10-06-34

I want to see table view of showing differences between these two timestamps:
Screenshot from 2024-03-15 10-07-50

How this could be achieved?

I think solution for this would be pretty powerfull for multiple table formatted data scenarios regarding Network devices (Routing table, MAC table, ARP table etc) and may be usefull for other industries as well.

Any comments are highly appreciated.

2 Likes

Hi @JaakkoR and welcome to the Grafana forum and thank you for a nice description of your situation.

Are you using InfluxQL, Flux, or SQL? Given your intention to write values at a moment-in-time and then do comparisons later, I believe Flux would be the better tool for this.

1 Like

Hi @grant2 and thanks for the reply. I’m open to any query language. I seeking for solution with what-ever-it-takes mentality.

I have done some trials with InfluxQL related to the First goal. In my research I found Flux might be better for this but today found out it is going to be depracated. So I’m curious is is still the way to go I should dig deeper?

@JaakkoR
This should be used as the gold standard template for how to ask a question in any forum!!!

That said are you willing to move to another database type
Mysql
Ms sql
Postgres

Why:
Flux is going away
Influxql imo is not mature enough for what you want to do

Yes if that is best way to achieve the goal. Is it then doable in Grafana if db is SQL?

Then I just need to forward all time series metrics from gnmi to influx and table type data to SQL and grafana could be used visualize both.

let’s try with some sample DDL and DML.

Please post something like this

create table vader(
prefix varchar(50)  not null,
capture_date datetime not null,
and rest of columns and data type
)

insert into vader
select '1.1.1.1', 'djfdjfkd' union
select '1.3.5

but a key component is the column that will help the 30 minutes ago vs now comparison. what key field is that to tie current with historical otherwise how can you compare?

etc, we can do a quick POC on our SQL server to proof this out

Just to understand the idea first:

Now when relying on non-TSDB we can have table for routing table (let’s call it RIB (Routing Information Base)) in the DB. Then events just modify the state of the table to reflect reality.

Achieving the First goal is then just visualizing the table in a given point in time (end of selected time range), right?

What about the Second goal? Oh, your question is related to this, right?

The key field in routing table is prefix. I’m not sure if I understood the question right.

How the query could work? We can’t query 30m ago just by ignoring more recent updates. History needs to be stored.

Ultimately I would like to compare between start and end of selected grafana time range but fixed 30 min would work first.

Anything can be tsdb even a csv file as long as it has datetime. :wink:

Wow, thanks! I need to play with it.

What SQL you are using?

1 Like

Microsoft sql server but doesnt matter can be done with mysql and postgres. The query has issues with the min max. It has to account for the time range otherwise it will get the min in the whole table so needs some tlc

I’m new to the SQL. Is routing.sql something I should run using SQL client or should it work via Grafana?

1 Like

I have postgres and I tried to run it to the db like this:

psql -h localhost -p 5432 -a -f routing.sql

But I get this error:

psql:routing.sql:86: ERROR:  relation "routing" does not exist
LINE 9:    from routing t

I got syntax right for postgres (with help of chatgpt :slightly_smiling_face: ) and now I have this in grafana:

Great! Thanks for the help. Now I’m in good position to start working on it.

1 Like

So the solution provided is outside of grafana so better continuing this convo in postgres forum