Skip to content

Commit

Permalink
Merge pull request #264 from nokia/asciigraph-output
Browse files Browse the repository at this point in the history
add asciigraph output
  • Loading branch information
karimra authored Nov 6, 2023
2 parents f4c7436 + 0bfa527 commit 7afa0af
Show file tree
Hide file tree
Showing 7 changed files with 702 additions and 3 deletions.
155 changes: 155 additions & 0 deletions docs/user_guide/outputs/asciigraph_output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
`gnmic` supports displaying collected metrics as an ASCII graph on the terminal.
The graph is generated using the [asciigraph](https://github.com/guptarohit/asciigraph) package.

### Configuration sample

```yaml

outputs:
output1:
# required
type: asciigraph
# string, the graph caption
caption:
# integer, the graph height. If unset, defaults to the terminal height
height:
# integer, the graph width. If unset, defaults to the terminal width
width:
# float, the graph minimum value for the vertical axis.
lower-bound:
# float, the graph minimum value for the vertical axis.
upper-bound:
# integer, the graph left offset.
offset:
# integer, the decimal point precision of the label values.
precision:
# string, the caption color. one of ANSI colors.
caption-color:
# string, the axis color. one of ANSI colors.
axis-color:
# string, the label color. one of ANSI colors.
label-color:
# duration, the graph refresh timer.
refresh-timer: 1s
# string, one of `overwrite`, `if-not-present`, ``
# This field allows populating/changing the value of Prefix.Target in the received message.
# if set to ``, nothing changes
# if set to `overwrite`, the target value is overwritten using the template configured under `target-template`
# if set to `if-not-present`, the target value is populated only if it is empty, still using the `target-template`
add-target:
# string, a GoTemplate that allows for the customization of the target field in Prefix.Target.
# it applies only if the previous field `add-target` is not empty.
# if left empty, it defaults to:
# {{- if index . "subscription-target" -}}
# {{ index . "subscription-target" }}
# {{- else -}}
# {{ index . "source" | host }}
# {{- end -}}`
# which will set the target to the value configured under `subscription.$subscription-name.target` if any,
# otherwise it will set it to the target name stripped of the port number (if present)
target-template:
# list of processors to apply on the message before writing
event-processors:
# bool enable debug
debug: false
```
### Example
This example shows how to use the `asciigraph` output.

gNMIc config

```shell
cat gnmic_asciiout.yaml
```

```yaml
targets:
clab-nfd33-spine1-1:
username: admin
password: NokiaSrl1!
skip-verify: true
subscriptions:
sub1:
paths:
- /interface[name=ethernet-1/3]/statistics/out-octets
- /interface[name=ethernet-1/3]/statistics/in-octets
stream-mode: sample
sample-interval: 1s
encoding: ascii
outputs:
out1:
type: asciigraph
caption: in/out octets per second
event-processors:
- rate
processors:
rate:
event-starlark:
script: rate.star
```

Starlark processor

```shell
cat rate.star
```

```python
cache = {}
values_names = [
'/interface/statistics/out-octets',
'/interface/statistics/in-octets'
]
N=2
def apply(*events):
for e in events:
for value_name in values_names:
v = e.values.get(value_name)
# check if v is not None and is a digit to proceed
if not v:
continue
if not v.isdigit():
continue
# update cache with the latest value
val_key = "_".join([e.tags["source"], e.tags["interface_name"], value_name])
if not cache.get(val_key):
# initialize the cache entry if empty
cache.update({val_key: []})
if len(cache[val_key]) > N:
# remove the oldest entry if the number of entries reached N
cache[val_key] = cache[val_key][1:]
# update cache entry
cache[val_key].append((int(v), e.timestamp))
# get the list of values
val_list = cache[val_key]
# calculate rate
e.values[value_name+"_rate"] = rate(val_list)
e.values.pop(value_name)
return events
def rate(vals):
previous_value, previous_timestamp = None, None
for value, timestamp in vals:
if previous_value != None and previous_timestamp != None:
time_diff = (timestamp - previous_timestamp) / 1000000000 # 1 000 000 000
if time_diff > 0:
value_diff = value - previous_value
rate = value_diff / time_diff
return rate
previous_value = value
previous_timestamp = timestamp
return 0
```

<script async id="asciicast-617477" src="https://asciinema.org/a/617477.js"></script>
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/gorilla/mux v1.8.0
github.com/gosnmp/gosnmp v1.35.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/guptarohit/asciigraph v0.5.6
github.com/hairyhenderson/gomplate/v3 v3.11.5
github.com/hashicorp/consul/api v1.25.1
github.com/hashicorp/golang-lru/v2 v2.0.7
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,8 @@ github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWf
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/guptarohit/asciigraph v0.5.6 h1:0tra3HEhfdj1sP/9IedrCpfSiXYTtHdCgBhBL09Yx6E=
github.com/guptarohit/asciigraph v0.5.6/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag=
github.com/hairyhenderson/go-fsimpl v0.0.0-20220529183339-9deae3e35047 h1:nSSfN9G8O8XXDqB3aDEHJ8K+0llYYToNlTcWOe1Pti8=
github.com/hairyhenderson/go-fsimpl v0.0.0-20220529183339-9deae3e35047/go.mod h1:30RY4Ey+bg+BGKBufZE2IEmxk7hok9U9mjdgZYomwN4=
github.com/hairyhenderson/gomplate/v3 v3.11.5 h1:LSDxCw8tWC/ltOzbZaleUNjGJOIEgnR/SN3GM9eClsA=
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ nav:
- TCP: user_guide/outputs/tcp_output.md
- UDP: user_guide/outputs/udp_output.md
- SNMP: user_guide/outputs/snmp_output.md
- ASCII Graph: user_guide/outputs/asciigraph_output.md

- Processors:
- Introduction: user_guide/event_processors/intro.md
Expand Down
1 change: 1 addition & 0 deletions outputs/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package all

import (
_ "github.com/openconfig/gnmic/outputs/asciigraph_output"
_ "github.com/openconfig/gnmic/outputs/file"
_ "github.com/openconfig/gnmic/outputs/gnmi_output"
_ "github.com/openconfig/gnmic/outputs/influxdb_output"
Expand Down
Loading

0 comments on commit 7afa0af

Please sign in to comment.