Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add asciigraph output #264

Merged
merged 1 commit into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/huandu/xstrings v1.4.0
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