How to compare the current series of data with previous series using kapacitor (tick script)

kapacitor

#11

I think the issue here is that the .id() property on the |alert() node is set to a specific value. Kapacitor uses the alert ID internally (it’s not just an external designation) to keep track of separate alerts. Each alert needs to have it’s own specific “id” so that each triggered alert can then be resolved when the threshold is no longer met. Right now, every alert is being assigned the same ID (/jobs:jobs/telemetry-measurement:measurement/measurement=change/query=change) so only one alert is technically being triggered.

In your case, you’ll probably want to break out your alerts by tag values device and name. The alert ID string would look something like this:

.id('kapacitor/{{ index .Tags "device" }}/{{ index .Tags "name" }}')

Check out the docs for other the template options for the ID.


#12

Hey Rajesh,

What are you trying to achieve with


var result=data
|alert()
.id('/jobs:jobs/telemetry-measurement:measurement/measurement=statechange/query=statechange')
.stateChangesOnly()
.crit(lambda: 1==1)
.log('/tmp/result.tmp')

I’m not sure I totally follow what the point of this is.

I think if we change

dbrp "test"."autogen"

var keys= ['Devicename','Interfacename']
var data = stream
|from()
.measurement('statechange')
.groupBy(keys)
|window()
.period(1m)
.every(1m)
|alert()
.info(lambda: "state" == 'UP')
.warn(lambda: "state" == 'DOWN')

where the info and warn are on the same alert node, we should see both types of alerts.


#13

Hi Michael,

Lets say we have only 2 states which are UP and DOWN. Whenever it changes from one state to another then only alert should happen. That’s why we have used 1==1 with statechangesonly property. So , now whenever there is some change happens then only alert will happen.

As per your snippet, it will raise two alarms with different levels based on status.

Let me know if you need further info.


#14

Hi,

Is this the only case with Statechangesonly or for generic case. Since, we have used .id with static value for all our other use cases and we are getting continuous alert whenever condition matches. Below is one such example.

dbrp "test"."autogen"

var interface_status = stream
|from()
.measurement('test')
.groupBy(*)
|window()
.period(1m)
.every(1m)

var up_data = interface_status
|where(lambda: "status" == 'UP')
|count('status')


var down_data = interface_status
|where(lambda: "status" == 'DOWN')
|count('status')

up_data
|join(down_data)
.as('up', 'down')
|alert()
.id('/jobs:jobs/telemetry-measurement:measurement/measurement=test/query=test')
.crit(lambda: "up.count" > 5 AND "down.count" >= 0)
.log('/tmp/out.tmp')

#15

What about

dbrp "test"."autogen"

var keys= ['Devicename','Interfacename']
var data = stream
|from()
.measurement('statechange')
.groupBy(keys)
|window()
.period(1m)
.every(1m)
|changeDetect('state')
|alert()
  .info(lambda: TRUE)

#16

Hi Michael,

I tried out with changeDetect but it is giving continuous message though there is no change. What we want is it should event based not the periodic updates. If there is some change in state of interface then only alert should happen. But it is continuously giving the update.

Requirement is like this:

We have thousands of devices (D1, D2, D3…so on) – TAG’s

Each device with no.of interfaces (Intf1,Intf2,Intf3…etc) -TAGS

Each interface will have status (UP/DOWN/other)–Fields

we want to get an alert whenever there is some change in state of interface for that device. So , that is why we tried grouping with Devicename,Interfacename and other combination with Devicename,Interfacename,State.

However, i have tried by removing the period and every, still no luck.

Both of them giving the correct result but continuous alert should not be the case. Because change is not continuously happening.

Query1: How to make this only trigger based not continuous ?

Query2 : How to access the variable’s field (More details on this same thread above)


#17

Hey Rajesh

Off hand it sounds like we might not be grouping all the points into their respective series and therefore it feels like we are continuously alerts since points are coming together from different series. One thing we could try would be to use groupBy(*).

dbrp "test"."autogen"

var data = stream
|from()
.measurement('statechange')
.groupBy(*)
|window()
.period(1m)
.every(1m)
|changeDetect('state')
|alert()
  .info(lambda: TRUE)

If that doesn’t solve the issue, what would be helpful is a toy example using data expressed in line protocol with examples of data that you would expect to trigger an alert.

Something like the following example expressing the average of a series for a time window:

With data

cpu,host=A value=10 T0
cpu,host=B value=10 T0

cpu,host=A value=12 T1
cpu,host=B value=20 T1

Where points are grouped into their individual series, and windowed into the period [T0,T1], I expect

cpu,host=A value=10 T0
cpu,host=A value=12 T1

not to alert because the average cpu value for host=A is 11 which is less than 15.

And I expect

cpu,host=B value=15 T0
cpu,host=B value=20 T1

to alert because the average cpu value for host=B is 15 which is equal 15.


#18

Hi Michael,

The solution is not working for our usecase. Because in our case, each series will be one interface details w.r.t that particular device.

The actual data is like below:

{“id”:"/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf",“message”:"/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf is INFO",“details”:"{\u0026#34;Name\u0026#34;:\u0026#34;intftest\u0026#34;,\u0026#34;TaskName\u0026#34;:\u0026#34;intf\u0026#34;,\u0026#34;Group\u0026#34;:\u0026#34;device=172.16.18.176,name=Null0,path=openconfig-interfaces:interfaces/interface,system_id=IOSXR02\u0026#34;,\u0026#34;Tags\u0026#34;:{\u0026#34;device\u0026#34;:\u0026#34;172.16.18.176\u0026#34;,\u0026#34;name\u0026#34;:\u0026#34;Null0\u0026#34;,\u0026#34;path\u0026#34;:\u0026#34;openconfig-interfaces:interfaces/interface\u0026#34;,\u0026#34;system_id\u0026#34;:\u0026#34;IOSXR02\u0026#34;},\u0026#34;ServerInfo\u0026#34;:{\u0026#34;Hostname\u0026#34;:\u0026#34;infra-kapacitor-6d4d66658b-jqb4f\u0026#34;,\u0026#34;ClusterID\u0026#34;:\u0026#34;84decbe8-63f8-4648-a849-96dd76a1d301\u0026#34;,\u0026#34;ServerID\u0026#34;:\u0026#34;2732b57a-46c5-4e29-bd02-44a9548e34b6\u0026#34;},\u0026#34;ID\u0026#34;:\u0026#34;/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf\u0026#34;,\u0026#34;Fields\u0026#34;:{\u0026#34;_sequence\u0026#34;:\u0026#34;2250230\u0026#34;,\u0026#34;_timestamp\u0026#34;:\u0026#34;1531698815825\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/index\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/admin-status\u0026#34;:\u0026#34;UP\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-broadcast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-discards\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-errors\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-multicast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-octets\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-unicast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-unknown-protos\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/last-clear\u0026#34;:\u0026#34;2018-04-16T02:37:37Z\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-broadcast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-discards\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-errors\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-multicast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-octets\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-unicast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/description\u0026#34;:\u0026#34;\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/index\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/last-change\u0026#34;:\u0026#34;7852595\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/mtu\u0026#34;:\u0026#34;1500\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/oper-status\u0026#34;:\u0026#34;UP\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/type\u0026#34;:\u0026#34;iana-if-type:other\u0026#34;},\u0026#34;Level\u0026#34;:\u0026#34;INFO\u0026#34;,\u0026#34;Time\u0026#34;:\u0026#34;2018-07-15T23:53:35.825Z\u0026#34;,\u0026#34;Duration\u0026#34;:122551000000,\u0026#34;Message\u0026#34;:\u0026#34;/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf is INFO\u0026#34;}\n",“time”:“2018-07-15T23:53:35.825Z”,“duration”:122551000000,“level”:“INFO”,“data”:{“series”:[{“name”:“intftest”,“tags”:{“device”:“172.16.18.176”,“name”:“Null0”,“path”:“openconfig-interfaces:interfaces/interface”,“system_id”:“IOSXR02”},“columns”:[“time”,"_sequence","_timestamp",“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/index”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/admin-status”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-broadcast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-discards”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-errors”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-multicast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-octets”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-unicast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-unknown-protos”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/last-clear”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-broadcast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-discards”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-errors”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-multicast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-octets”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-unicast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/description”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/index”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/last-change”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/mtu”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/oper-status”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/type”],“values”:[[“2018-07-15T23:53:35.825Z”,“2250230”,“1531698815825”,“0”,“UP”,“0”,“0”,“0”,“0”,“0”,“0”,“0”,“2018-04-16T02:37:37Z”,“0”,“0”,“0”,“0”,“0”,“0”,"",“0”,“7852595”,“1500”,“UP”,“iana-if-type:other”]]}]},“previousLevel”:“INFO”,“recoverable”:true}
{“id”:"/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf",“message”:"/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf is INFO",“details”:"{\u0026#34;Name\u0026#34;:\u0026#34;intftest\u0026#34;,\u0026#34;TaskName\u0026#34;:\u0026#34;intf\u0026#34;,\u0026#34;Group\u0026#34;:\u0026#34;device=172.16.18.176,name=PW-Ether7,path=openconfig-interfaces:interfaces/interface,system_id=IOSXR02\u0026#34;,\u0026#34;Tags\u0026#34;:{\u0026#34;device\u0026#34;:\u0026#34;172.16.18.176\u0026#34;,\u0026#34;name\u0026#34;:\u0026#34;PW-Ether7\u0026#34;,\u0026#34;path\u0026#34;:\u0026#34;openconfig-interfaces:interfaces/interface\u0026#34;,\u0026#34;system_id\u0026#34;:\u0026#34;IOSXR02\u0026#34;},\u0026#34;ServerInfo\u0026#34;:{\u0026#34;Hostname\u0026#34;:\u0026#34;infra-kapacitor-6d4d66658b-jqb4f\u0026#34;,\u0026#34;ClusterID\u0026#34;:\u0026#34;84decbe8-63f8-4648-a849-96dd76a1d301\u0026#34;,\u0026#34;ServerID\u0026#34;:\u0026#34;2732b57a-46c5-4e29-bd02-44a9548e34b6\u0026#34;},\u0026#34;ID\u0026#34;:\u0026#34;/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf\u0026#34;,\u0026#34;Fields\u0026#34;:{\u0026#34;_sequence\u0026#34;:\u0026#34;2250230\u0026#34;,\u0026#34;_timestamp\u0026#34;:\u0026#34;1531698815825\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/index\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/admin-status\u0026#34;:\u0026#34;DOWN\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-discards\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-unicast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-discards\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-unicast-pkts\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/description\u0026#34;:\u0026#34;\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/index\u0026#34;:\u0026#34;0\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/last-change\u0026#34;:\u0026#34;1531698816\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/mtu\u0026#34;:\u0026#34;1514\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/oper-status\u0026#34;:\u0026#34;DOWN\u0026#34;,\u0026#34;openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/type\u0026#34;:\u0026#34;iana-if-type:ifPwType\u0026#34;},\u0026#34;Level\u0026#34;:\u0026#34;INFO\u0026#34;,\u0026#34;Time\u0026#34;:\u0026#34;2018-07-15T23:53:35.825Z\u0026#34;,\u0026#34;Duration\u0026#34;:122551000000,\u0026#34;Message\u0026#34;:\u0026#34;/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf is INFO\u0026#34;}\n",“time”:“2018-07-15T23:53:35.825Z”,“duration”:122551000000,“level”:“INFO”,“data”:{“series”:[{“name”:“intftest”,“tags”:{“device”:“172.16.18.176”,“name”:“PW-Ether7”,“path”:“openconfig-interfaces:interfaces/interface”,“system_id”:“IOSXR02”},“columns”:[“time”,"_sequence","_timestamp",“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/index”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/admin-status”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-discards”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/in-unicast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-discards”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/counters/out-unicast-pkts”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/description”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/index”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/last-change”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/mtu”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/oper-status”,“openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/type”],“values”:[[“2018-07-15T23:53:35.825Z”,“2250230”,“1531698815825”,“0”,“DOWN”,“0”,“0”,“0”,“0”,"",“0”,“1531698816”,“1514”,“DOWN”,“iana-if-type:ifPwType”]]}]},“previousLevel”:“INFO”,“recoverable”:true}

I feel, the solution which you given will work when we have single series which will provide the data about all the interfaces w.r.t all devices.

Let me know, if you need any further info on this.

The tick script which i have used:

dbrp “atom”.“autogen”

var data = stream
|from()
.measurement(‘intftest’)
.groupBy(*)
|window()
.period(1m)
.every(1m)

|changeDetect(‘openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/admin-status’)
|alert()
.id(’/jobs:jobs/telemetry-measurement:measurement/measurement=intf/query=intf’)
.info(lambda: TRUE)
.log(’/tmp/rajesh.tmp’)


#19

Hey Rajesh

Can you offer a bit more insight other than

The solution is not working for our usecase. Because in our case, each series will be one interface details w.r.t that particular device.

Specifically what would be useful is a toy example with data expressed line protocol.


#20

Here is the example for with sample data:

test, Device=Device1, Interfacename=Interface1 , status=UP , MTU=1500 , timestamp= T1 ***
test, Device=Device1, Interfacename=Interface2 , status=DOWN , MTU=1500 , timestamp= T2
test, Device=Device2, Interfacename=Interface1 , status=DOWN , MTU=1500 , timestamp= T2
test, Device=Device2, Interfacename=Interface2 , status=UP , MTU=1505 , timestamp= T3
test, Device=Device1, Interfacename=Interface1 , status=DOWN , MTU=1500 , timestamp= T3 ***
test, Device=Device1, Interfacename=Interface3 , status=UP , MTU=1500 , timestamp= T6

For the device1 Interface1 status got changed at T3, so First alert for that series should happen there.

Here test is the measurement name.

Basically, we are comparing the previous(history) series(line protocol) with current and raising an alert if any change happens on that particular interface w.r.t that device.


#21

from your example it’s hard to tell what are fields, tags, etc. Are Device, Interfacename, and status tags or fields?


#22

Device and Interface name – tags
Interface Status – Field


#23

Using the following tickscript

dbrp "test"."autogen"

var data = stream
    |from()
        .measurement('test')
        .groupBy(*)
    |changeDetect('status')
    |alert()
        .info(lambda: TRUE)
P0: test,Device=Device1,Interfacename=Interface1 status="UP",MTU=1500 T0
P1: test,Device=Device1,Interfacename=Interface2 status="DOWN",MTU=1500 T1
P2: test,Device=Device2,Interfacename=Interface1 status="DOWN",MTU=1500 T2
P3: test,Device=Device2,Interfacename=Interface2 status="UP",MTU=1500 T3
P4: test,Device=Device1,Interfacename=Interface1 status="DOWN",MTU=1500 T4
P5: test,Device=Device1,Interfacename=Interface3 status="UP",MTU=1500 T5

I get alerts for every point because each point has changed from it’s previous value.

For points P0, P1, P2, P3, and P5 I get an alert because there the state was changed from null to a value; this should only happen at first. After things have been primed it should not occur.

For point P4, I get an alert because the series test,Device=Device1,Interfacename=Interface1 changed from status="UP" in P0 to status="DOWN" in P4.

If I further wrote the data

P6: test,Device=Device1,Interfacename=Interface1 status="DOWN",MTU=1500 T6
P7: test,Device=Device1,Interfacename=Interface1 status="DOWN",MTU=1500 T7
P8: test,Device=Device1,Interfacename=Interface1 status="UP",MTU=1500 T8
P9: test,Device=Device1,Interfacename=Interface3 status="UP",MTU=1500 T9
P10: test,Device=Device1,Interfacename=Interface3 status="DOWN",MTU=1500 T10

I would receive alerts for P8 since and P10, but not for P6, P7, and P9.

Is this the behavior that you’re looking for? If not, what is different?


#24

Thanks @michael

Our requirement is to get whenever there is some change in the state ‘n’ no.of times (which should not include the first one as you mentioned). Though, it is changed from null to some value.

For example, if the interface1 state has changed from UP --> DOWN --> UP --> DOWN–> UP–>DOWN

Here, 3 events happened. Each event is state change from UP–>DOWN

Another, usecase is to identify all the state changes UP --> DOWN --> UP --> DOWN–> UP–>DOWN
here, 5 state changes happened in last 1minute then we should get alert.

Let me know, if you need any other info on this.


#25

For example, if the interface1 state has changed from UP --> DOWN --> UP --> DOWN–> UP–>DOWN

This can be done with

dbrp "test"."autogen"

var data = stream
    |from()
        .measurement('test')
        .groupBy(*)
    |changeDetect('status')
    |alert()
        .info(lambda: "status" == 'DOWN')

and

Another, usecase is to identify all the state changes UP --> DOWN --> UP --> DOWN–> UP–>DOWN
here, 5 state changes happened in last 1minute then we should get alert.

This is possible with the tickscript we had previously

dbrp "test"."autogen"

var data = stream
    |from()
        .measurement('test')
        .groupBy(*)
    |changeDetect('status')
    |alert()
        .info(lambda: TRUE)

The hard part is to make things not trigger for their first value.

I think we can add |where(lambda: count() > 1) so that we skip the first time it happens.

dbrp "test"."autogen"

var data = stream
    |from()
        .measurement('test')
        .groupBy(*)
    |changeDetect('status')
    |where(lambda: count() > 1)
    |alert()
        .info(lambda: TRUE)

I think having the count there for both scripts would be helpful.

Does this achieve what you’re trying to do?


#26

Logic looks fine to me. I will run this with actual data.

Meanwhile, can you answer another question, which is at the top of our discussion in the same thread.

var current = stream
|from()
.measurement(‘test’)
.groupBy()
|window()
.period(1m)
.every(1m)

var old = current
|shift(-1m)

|alert()
.id(’/jobs:jobs/telemetry-measurement:measurement/measurement=test/query=test’)
.crit(lambda: ((‘current.tag1’== ‘old.tag1’)AND(‘current.tag2’==‘old.tag2’)AND(‘current.field1’ != ‘old.field1’)))
.log(’/tmp/out.tmp’)

Especially, i had a doubt at lambda condition: there tag1 and tag2 are tags and field1 is the field. And where the single or double quotes can be added…

It required for us to store in one variable and compare with some other values later.

q1: how to use the tags/fields from the variable?
q2: How to compare with plain string with varible’s field?
ex: temp1.field1==“hello”

more information can be find out at How to compare 2 consecutive series of data and the ways to access/compare variables in Tick?

Due to duplicate in the content it is closed.

It is useful for number of our usecases.


#27

q1: how to use the tags/fields from the variable?
q2: How to compare with plain string with varible’s field?
ex: temp1.field1==“hello”

I’m not sure I follow, can you give me an example with the data in line protocol and an example of what output you want.


#28

We have 2 Devices: Device1, Device2. device-id and interface-name are tags and all others fields.

We have 3 measurements: one for device1 neighbor details, one for device2 neighbor details, another one for MTU details of device1, device2

First, we have to identify the connected interfaces between them. the condition will be local interface-name or port-id is equal to remote sides receiving-interface-name.

Then we have to check the other value (MTU) on those interfaces if the value is different then raise a critical alert.

Measurement1:
m1, device-id=Device1,remote-device=Device2,port-id=Interface1,receiving-interface-name=Interface1,timestamp= T1 --> S2**
m1, device-id=Device1,remote-device=Device2,port-id=Interface2,receiving-interface-name=Interface4,timestamp= T1 --> S3
m1, device-id=Device1,remote-device=Device2,port-id=Interface3,receiving-interface-name=Interface5,timestamp= T1 --> S4
m1, device-id=Device1,remote-device=Device2,port-id=Interface6,receiving-interface-name=Interface8,timestamp= T1 --> S4**

Measurement2:
m2, device-id=Device2,remote-device=Device1,port-id=Interface1,receiving-interface-name=Interface1,timestamp= T1 --> S1 **
m2, device-id=Device2,remote-device=Device1,port-id=Interface2,receiving-interface-name=Interface19,timestamp= T1 --> S2
m2, device-id=Device2,remote-device=Device3,port-id=Interface4,receiving-interface-name=Interface2,timestamp= T2–> S3
m2, device-id=Device2,remote-device=Device1,port-id=Interface5,receiving-interface-name=Interface11,timestamp= T1 --> S4
m2, device-id=Device2,remote-device=Device1,port-id=Interface8,receiving-interface-name=Interface6,timestamp=T1–> S4**

Now, we got the neighboring devices based on the above 2 measurements. We have to use those device-id’s and port-id’s with below measurement to get MTU mismatched interfaces. Now, we have to check the MTU value of interface1 of device1 and interface1 of devices2 && interface6 of Device1 and interface8 of device2. If there is a mismatch we have to report it.

Here, even we can use a single measurement(m1) alone and compare the MTU values with m3.

Measurement3:
m3, device-id=Device1,interface-name=Interface1,MTU=1650, timestamp=T1 --> S1**
m3, device-id=Device1,interface-name=Interface2,MTU=1550, timestamp=T1 --> S2
m3, device-id=Device1,interface-name=Interface3,MTU=1600, timestamp=T1 --> S3
m3, device-id=Device1,interface-name=Interface6,MTU=1550, timestamp=T1 --> S4
m3, device-id=Device2,interface-name=Interface1,MTU=1600, timestamp=T1 --> S5**
m3, device-id=Device2,interface-name=Interface2,MTU=1550, timestamp=T1 --> S6
m3, device-id=Device2,interface-name=Interface4,MTU=1600, timestamp=T1 --> S7
m3, device-id=Device2,interface-name=Interface8,MTU=1550, timestamp=T1 --> S8

**

Result will be Device1, interface1,MTU=1650 and Device2,Interface1,MTU=1600.

**

We have to use a stream instead of batch. If it is not possible with streaming node then we can go for a batch.

dbrp “ncx”.“autogen”
var output = batch
|query(‘select “port-id”,“receiving-interface-name”,“neigh-device-id”,“device-id” from “m1”’)
.period(1m)
.every(1m)
.groupBy(*)

var output_neighbor = batch
|query(‘select “port-id”,“receiving-interface-name”,“neigh-device-id”,“device-id” from “m2”’)
.period(1m)
.every(1m)
.groupBy(*)

var mtu = ‘select “mtu” from “m3” where interface-name=‘output’.“receiving-interface-name”’

var intf_name = ‘select “interface-name” from “m2” where “output.device-id == output_neighbor.device-id” AND “output.port-id=output_neighbor.receiving-interface-name” AND “output.receiving-interface-name=output_neighbor.port-id”’

var mtu_neighbor = ‘select “mtu” from “m3” where interface-name=’+intf_name
|alert()
.crit(lambda: (mtu == mtu_neighbor))
.log(’/tmp/out.tmp’)

Here, we want to know how to access a particular field/tag from variable.

> var mtu = 'select “mtu” from “m3” where interface-name=‘output’.“receiving-interface-name”'

here we are accessing the receiving-interface-a name from variable output.

Is there anyway to write nested select queries in Influx?


#29

@michael I have tried with script which you have provided… But no luck.

It is giving alert only for the first interface which matches that condition. Only one time the alert has been triggered. There are continuous changes on the interfaces state.

Let’s say Interface1 status got changed at T2 and then there are several other interfaces where their status got changed later like Inteface2, Interface3…etc… But the alert has been triggered only for the Interface1.

can you check on this.

dbrp “atom”.“autogen”

var data = stream
|from()
.measurement(‘InterfaceFlapping’)
.groupBy(*)
|changeDetect(‘openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state/admin-status’)
|where(lambda: count() > 1)
|alert()
.info(lambda: TRUE)
.log(’/tmp/result.tmp’)


#30

Can you provide data in line protocol to reproduce the issue.