Compare commits

...

34 Commits

Author SHA1 Message Date
Annika Hannig
436a080c04
refactoring and fixed missing init in struct 2024-11-20 17:22:19 +01:00
Annika Hannig
b91420dac9 moved metrics 2024-11-20 17:02:50 +01:00
Annika Hannig
bc395d021d some refactoring 2024-11-20 16:10:56 +01:00
Annika Hannig
c33bf96597 renamed configuration flag 2024-11-20 14:13:01 +01:00
Annika Hannig
bca0f75c46
Merge pull request #169 from iaa-inc/prometheus
Initial Prometheus work
2024-11-20 14:08:13 +01:00
Nick Pratley
728f44b32b whoops 2024-10-28 10:11:23 +11:00
Nick Pratley
89b333ecf7 rename peer <> neighbor, clean up readme merge 2024-10-28 10:10:37 +11:00
Nick Pratley
1fb8f9a7c4 Merge remote-tracking branch 'refs/remotes/alice/develop' into prometheus
# Conflicts:
#	README.md
2024-10-28 10:05:19 +11:00
Nick Pratley
4aeeb8bbdf set to 5 seconds not 1 second 2024-10-17 11:44:51 +11:00
Nick Pratley
2121286c5d fix config file wording 2024-10-17 11:35:23 +11:00
Nick Pratley
b73c8b33d8 docs for prom 2024-10-17 11:34:06 +11:00
Nick Pratley
8f8629c55a initial prometheus work 2024-10-17 11:29:36 +11:00
Annika Hannig
ae069e2ba6
Merge pull request #141 from jof/jof/bgplgd-neighbor-states
Sort bgplgd neighbor states
2024-09-27 14:22:03 +02:00
Annika Hannig
91670f7db0
Merge pull request #139 from jof/patch-1
Add SFMIX Alice Instance
2024-03-05 16:03:16 +01:00
Annika Hannig
0cfee83602
Merge branch 'develop' into patch-1 2024-03-05 16:03:03 +01:00
Annika Hannig
37caf859c0
Merge pull request #146 from jof/jof/customizable-logo
Make it possible to customize the sidebar logo
2024-02-29 11:37:02 +01:00
Annika Hannig
24770bc958
Merge pull request #144 from jof/jof/gobgp-neighborsstatus
GoBGP: Construct NeighborsStatus response
2024-02-29 10:20:46 +01:00
Annika Hannig
c2816008b2
Merge pull request #147 from jof/jof/describe-config
alice.conf: Add some comments about section usage
2024-02-29 10:20:16 +01:00
Annika Hannig
7da417313e
Merge pull request #148 from johannesmoos/jmo/birdwatcher-source-logging
Remove multi_table specific log output when using single_table birdwatcher sources
2024-02-29 10:19:24 +01:00
Annika Hannig
c89dbb6816
Merge pull request #149 from johannesmoos/jmo/harmonize-store-logging
Harmonize neighbors and route store logging
2024-02-29 10:17:37 +01:00
Annika Hannig
ff2b694a8d
Merge pull request #150 from johannesmoos/jmo/update-readme
README: Update Alice-LG production examples and API endpoint list
2024-02-29 10:16:37 +01:00
Johannes Moos
d058a1d8a0
README: Update Alice-LG production examples and API endpoint list 2024-02-25 18:19:26 +01:00
Johannes Moos
304b44675b
Harmonize neighbors and route store logging 2024-02-24 14:13:54 +01:00
Johannes Moos
66c0abb5aa
Remove multi_table specific log output when using single_table birdwatcher sources 2024-02-24 13:49:18 +01:00
Jonathan Lassoff
8565edd568 alice.conf: Add some comments about section usage 2024-02-22 20:33:25 -08:00
Jonathan Lassoff
7483977d16 Make it possible to customize the sidebar logo 2024-02-20 00:09:07 -08:00
Jonathan Lassoff
5ed1dea3ed GoBGP: Construct NeighborsStatus response 2024-02-18 16:41:25 -08:00
Jonathan Lassoff
8c428da635 Regroup and style idle connections 2024-02-17 22:11:48 -08:00
Jonathan Lassoff
ffcc5cbcf8 Sort bgplgd neighbor states 2024-02-17 21:12:40 -08:00
Jonathan Lassoff
e406222613
Add SFMIX Alice Instance
Add the SFMIX Alice instance to the production examples
2024-02-15 12:44:53 -08:00
Annika Hannig
914c7a4491
Merge pull request #136 from jof/jof/spelling
Various spelling fixes
2024-02-15 10:16:45 +01:00
Annika Hannig
cb0ac8af66
Merge pull request #137 from jof/jof/openbgpd-neighbor-ids
OpenBGPD: Restore Neighbor IDs
2024-02-15 10:11:34 +01:00
Jonathan Lassoff
848a8026ef OpenBGPD: Restore Neighbor IDs 2024-02-14 23:35:27 -08:00
Jonathan Lassoff
dfe58edcbd Various spelling fixes 2024-02-14 23:18:50 -08:00
60 changed files with 473 additions and 168 deletions

2
.gitignore vendored
View File

@ -35,3 +35,5 @@ var/
*coverage*
dist/
.idea/

View File

@ -3,22 +3,32 @@ __"No, no! The adventures first, explanations take such a dreadful time."__
_Lewis Carroll, Alice's Adventures in Wonderland & Through the Looking-Glass_
Take a look at Alice-LG production examples at:
- https://lg.de-cix.net/
- https://lg.ams-ix.net
- https://lg.bcix.de/
- https://lg.megaport.com/
- https://lg.netnod.se/
- https://alice-rs.linx.net/
- https://lg.ix.br/
- https://lg.bcix.de
- https://lg.dd-ix.net
- https://lg.de-cix.net
- https://glass.gigapix.pt
- https://lg.ix.br
- https://alice.sfmix.org/
- https://alice-rs.linx.net
- https://lg.megaport.com
- https://lg.netnod.se
- https://lg.s-ix.de
- https://lg.top-ix.org
- https://alice.sfmix.org/
- https://lg.ix.asn.au/
- https://lg.ix.nz/
And checkout the API at:
And check out the API at:
- https://lg.de-cix.net/api/v1/config
- https://lg.de-cix.net/api/v1/status
- https://lg.de-cix.net/api/v1/routeservers
- https://lg.de-cix.net/api/v1/routeservers/rs1_fra_ipv4/status
- https://lg.de-cix.net/api/v1/routeservers/rs1_fra_ipv4/neighbors
- https://lg.de-cix.net/api/v1/routeservers/rs1_fra_ipv4/neighbors/R194_106/routes
- https://lg.de-cix.net/api/v1/routeservers/rs1_fra_ipv4/neighbors/R194_106/routes/received
- https://lg.de-cix.net/api/v1/routeservers/rs1_fra_ipv4/neighbors/R194_106/routes/filtered
- https://lg.de-cix.net/api/v1/routeservers/rs1_fra_ipv4/neighbors/R194_106/routes/not-exported
- https://lg.de-cix.net/api/v1/lookup/prefix?q=217.115.0.0
@ -45,7 +55,7 @@ Currently Alice-LG supports the following APIs:
### Birdwatcher
Normally you would first install the [birdwatcher API](https://github.com/alice-lg/birdwatcher) directly on the machine(s) where you run [BIRD](http://bird.network.cz/) on
and then install Alice-LG on a seperate public facing server and point her to the afore mentioned [birdwatcher API](https://github.com/alice-lg/birdwatcher).
and then install Alice-LG on a separate public facing server and point her to the afore mentioned [birdwatcher API](https://github.com/alice-lg/birdwatcher).
This project was a direct result of the [RIPE IXP Tools Hackathon](https://atlas.ripe.net/hackathon/ixp-tools/)
just prior to [RIPE73](https://ripe73.ripe.net/) in Madrid, Spain.
@ -190,10 +200,10 @@ with the optional parameter (the "mountpoint" of the theme)
url_base = /theme
You can put assets (images, fonts, javscript, css) in
You can put assets (images, fonts, javascript, css) in
this folder.
Stylesheets and Javascripts are automatically included in
Stylesheets and JavaScripts are automatically included in
the client's html and are served from the backend.
Alice provides early stages of an extension API, which is for now
@ -221,6 +231,30 @@ Alice.onLayoutReady(function(page) {
For an example check out: https://github.com/alice-lg/alice-theme-example
## Metrics
When `enable_prometheus` is set to `true` in the configuration, Alice will expose metrics on `/metrics` in Prometheus
format.
The following metrics are available:
- `neighbor_state` - The state of the BGP peers (1 = established, 0 = not established)
- `neighbor_uptime` - The uptime of the BGP peers in seconds
- `routes_accepted` - The number of routes accepted from a peer
- `routes_filtered` - The number of routes filtered from a peer
- `routes_preferred` - The number of routes preferred from a peer
- `routes_received` - The number of routes received from a peer
The following labels are available:
- `neighbor_address` - The address of the BGP peer
- `neighbor_asn` - The ASN of the BGP peer
- `neighbor_description` - The description of the BGP peer
- `neighbor_id` - The ID of the BGP peer
- `route_server_group` - The group of the route server
- `route_server_id` - The ID of the route server
- `route_server_name` - The name of the route server
## Hacking
The client is a Single Page React Application.

View File

@ -133,6 +133,11 @@ func main() {
go routesStore.Start(ctx)
}
// Start exporting metrics
if cfg.Server.EnableMetrics {
go store.StartMetrics(ctx, neighborsStore)
}
// Start the Housekeeping
go store.StartHousekeeping(ctx, cfg)

View File

@ -53,6 +53,12 @@ routes_store_query_limit = 200000
# parsing a master4 table will take about 2.5 instead of 1.25 minutes.
stream_parser_throttle = 10000
# Enable metrics endpoint
# When `enable_metrics` is set to `true`, Alice will export metrics
# on `/metrics` in Prometheus (openmetrics) format.
# Default: false
enable_metrics = false
# [postgres]
# url = "postgres://postgres:postgres@localhost:5432/alice"
@ -83,8 +89,10 @@ routes_accepted_page_size = 250
routes_not_exported_page_size = 250
[rejection_reasons]
# a pair of a large BGP community value and a string to signal the processing
# results of route filtering
# BGP communities which, when present on a prefix represent the route as having
# been filtered out.
# Additionally, communities for searching and descriptions should be listed in
# the [bgp_communities] section of this configuration.
9033:65666:1 = An IP Bogon was detected
9033:65666:2 = Prefix is longer than 64
9033:65666:3 = Prefix is longer than 24
@ -140,7 +148,8 @@ unknown = 23042:1000:2
invalid = 23042:1000:4-*
# Define other known bgp communities
# Define known bgp communities which should be recognized and described in the
# Alice web UI
[bgp_communities]
1:23 = some tag
9033:65666:1 = ip bogon detected

20
go.mod
View File

@ -8,12 +8,15 @@ require (
github.com/jackc/pgx/v4 v4.18.1
github.com/julienschmidt/httprouter v1.3.0
github.com/osrg/gobgp v0.0.0-20190502094614-fd6618fed499
github.com/prometheus/client_golang v1.20.4
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.9.0
google.golang.org/grpc v1.60.1
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.14.1 // indirect
@ -23,12 +26,17 @@ require (
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/puddle v1.3.0 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect
google.golang.org/protobuf v1.32.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

48
go.sum
View File

@ -2,6 +2,10 @@ github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/armon/go-radix v0.0.0-20170727155443-1fca145dffbc/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
@ -26,7 +30,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
@ -85,16 +89,19 @@ github.com/jessevdk/go-flags v1.3.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.0.0-20160823170715-cfb55aafdaf3/go.mod h1:Bvhd+E3laJ0AVkG0c9rmtZcnhV0HQ3+c3YxxqTvc/gA=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.0.0-20160504234017-7cafcd837844/go.mod h1:sjUstKUATFIcff4qlB53Kml0wQPtJVc/3fWrmuUmcfA=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
@ -107,6 +114,8 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/osrg/gobgp v0.0.0-20190502094614-fd6618fed499 h1:uukk7LjpCIRDOnLORZG8m39q9y47SNsi56w0oUj3Xrg=
github.com/osrg/gobgp v0.0.0-20190502094614-fd6618fed499/go.mod h1:ORFhbKMbE5PuTrFOETR32zPLBMJUGIP1uMOqVyEhTAU=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
@ -115,7 +124,16 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
@ -149,8 +167,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/vishvananda/netlink v0.0.0-20170802012344-a95659537721/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netns v0.0.0-20170707011535-86bef332bfc3/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@ -177,8 +195,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@ -190,8 +208,8 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -212,8 +230,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -225,8 +243,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@ -251,11 +269,11 @@ google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=

View File

@ -72,7 +72,7 @@ type Rpki struct {
}
// Meta contains response meta information
// like cacheing time and cache ttl or the API version
// like caching time and cache ttl or the API version
type Meta struct {
Version string `json:"version"`
CacheStatus CacheStatus `json:"cache_status"`

View File

@ -130,7 +130,7 @@ func TestHasCommunity(t *testing.T) {
}
if bgp.HasLargeCommunity(Community{23, 42}) != false {
t.Error("23:42 should not be present in large commnuties")
t.Error("23:42 should not be present in large communities")
}
}

View File

@ -372,7 +372,7 @@ func NewSearchFilters() *SearchFilters {
return groups
}
// GetGroupByKey retrievs a search filter group
// GetGroupByKey retrieves a search filter group
// by a string.
func (s *SearchFilters) GetGroupByKey(key string) *SearchFilterGroup {
// This is an optimization (this is basically a fixed hash map,

View File

@ -12,7 +12,7 @@ used key.
*/
type LRUMap map[string]time.Time
// LRU retrievs the least recently used key
// LRU retrieves the least recently used key
func (lrumap LRUMap) LRU() string {
t := time.Now()
key := ""

View File

@ -30,7 +30,7 @@ func NewNeighborsCache(disabled bool) *NeighborsCache {
return cache
}
// Get retrievs the neighbors response from the cache, if present,
// Get retrieves the neighbors response from the cache, if present,
// and makes sure the information is still up to date.
func (cache *NeighborsCache) Get() *api.NeighborsResponse {
if cache.disabled {

View File

@ -37,7 +37,7 @@ func NewRoutesCache(disabled bool, size int) *RoutesCache {
return cache
}
// Get retrievs all routes for a given neighbor
// Get retrieves all routes for a given neighbor
func (cache *RoutesCache) Get(neighborID string) *api.RoutesResponse {
if cache.disabled {
return nil

View File

@ -29,7 +29,7 @@ var (
// not be identified from the section.
ErrSourceTypeUnknown = errors.New("source type unknown")
// ErrPostgresUnconfigured will occure when the
// ErrPostgresUnconfigured will occur when the
// postgres database URL is required, but missing.
ErrPostgresUnconfigured = errors.New(
"the selected postgres backend requires configuration")
@ -96,6 +96,7 @@ type ServerConfig struct {
DefaultAsn int `ini:"asn"`
EnableNeighborsStatusRefresh bool `ini:"enable_neighbors_status_refresh"`
StreamParserThrottle int `ini:"stream_parser_throttle"`
EnableMetrics bool `ini:"enable_metrics"`
}
// PostgresConfig is the configuration for the database
@ -731,7 +732,7 @@ func getSources(config *ini.File) ([]*SourceConfig, error) {
if len(sourceConfigSections) > 1 {
// The source is ambiguous
return nil, fmt.Errorf("%s has ambigous backends", section.Name())
return nil, fmt.Errorf("%s has ambiguous backends", section.Name())
}
// Configure backend
@ -795,15 +796,14 @@ func getSources(config *ini.File) ([]*SourceConfig, error) {
}
srcCfg.Birdwatcher = c
log.Println("Adding birdwatcher source",
c.Name, "of type", sourceType,
"with peer_table_prefix", peerTablePrefix,
"and pipe_protocol_prefix", pipeProtocolPrefix)
if c.AltPipeProtocolSuffix != "" {
log.Println(
"Alt pipe protocol prefix:", c.AltPipeProtocolPrefix,
"suffix:", c.AltPipeProtocolSuffix,
)
log.Println("Adding birdwatcher source", c.Name, "of type", sourceType)
if sourceType == "multi_table" {
log.Println(" Peer table prefix:", peerTablePrefix)
log.Println(" Pipe protocol prefix:", pipeProtocolPrefix)
if c.AltPipeProtocolSuffix != "" {
log.Println(" Alternative pipe protocol prefix:", c.AltPipeProtocolPrefix)
log.Println(" Alternative pipe protocol suffix:", c.AltPipeProtocolSuffix)
}
}
case SourceBackendGoBGP:
@ -945,6 +945,7 @@ func LoadConfig(file string) (*Config, error) {
RoutesStoreRefreshParallelism: 1,
NeighborsStoreRefreshParallelism: 1,
RoutesStoreQueryLimit: DefaultRoutesStoreQueryLimit,
EnableMetrics: true,
}
if err := parsedConfig.Section("server").MapTo(&server); err != nil {
return nil, err

View File

@ -35,7 +35,7 @@ func TestLoadConfigs(t *testing.T) {
t.Error(err)
}
if label != "some tag" {
t.Error("expcted to find example community 1:23 with 'some tag'",
t.Error("expected to find example community 1:23 with 'some tag'",
"but got:", label)
}

View File

@ -1,6 +1,6 @@
package decoders
// MapGet retrievs a key from an expected map
// MapGet retrieves a key from an expected map
// it falls back if the input is not a map
// or the key was not found.
func MapGet(m interface{}, key string, fallback interface{}) interface{} {
@ -15,7 +15,7 @@ func MapGet(m interface{}, key string, fallback interface{}) interface{} {
return val
}
// MapGetString retrievs a key from a map and
// MapGetString retrieves a key from a map and
// asserts its type is a string. Otherwise fallback
// will be returned.
func MapGetString(m interface{}, key string, fallback string) string {

View File

@ -1,3 +1,3 @@
// Package decoders contains functions for
// decoding backend responses into internal datastrucures.
// decoding backend responses into internal datastructures.
package decoders

View File

@ -113,7 +113,7 @@ func Duration(value interface{}, fallback time.Duration) time.Duration {
}
// DurationTimeframe decodes a duration: Bgpctl encodes
// this using fmt_timeframe, whiuch outputs a format similar
// this using fmt_timeframe, which outputs a format similar
// to that being understood by time.ParseDuration - however
// the time unit "w" (weeks) is not supported.
// According to https://github.com/openbgpd-portable/openbgpd-openbsd/blob/master/src/usr.sbin/bgpctl/bgpctl.c#L586-L591

View File

@ -67,7 +67,7 @@ func (s *Server) apiRoutesListReceived(
allRoutes := apiQueryFilterNextHopGateway(req, "q", result.Imported)
routes := api.Routes{}
// Apply other (commmunity) filters
// Apply other (community) filters
filtersApplied, err := api.FiltersFromQuery(req.URL.Query())
if err != nil {
return nil, err
@ -145,7 +145,7 @@ func (s *Server) apiRoutesListFiltered(
allRoutes := apiQueryFilterNextHopGateway(req, "q", result.Filtered)
routes := api.Routes{}
// Apply other (commmunity) filters
// Apply other (community) filters
filtersApplied, err := api.FiltersFromQuery(req.URL.Query())
if err != nil {
return nil, err
@ -223,7 +223,7 @@ func (s *Server) apiRoutesListNotExported(
allRoutes := apiQueryFilterNextHopGateway(req, "q", result.NotExported)
routes := api.Routes{}
// Apply other (commmunity) filters
// Apply other (community) filters
filtersApplied, err := api.FiltersFromQuery(req.URL.Query())
if err != nil {
return nil, err

View File

@ -31,7 +31,7 @@ func TestApiRoutesPagination(t *testing.T) {
}
if pagination.Page != 0 {
t.Error("Exptected current page to be 0, got:", pagination.Page)
t.Error("Expected current page to be 0, got:", pagination.Page)
}
// Check paginated slicing

View File

@ -48,7 +48,7 @@ func TestApiQueryFilterNextHopGateway(t *testing.T) {
)
if len(filtered) != 2 {
t.Error("Exptected 2 routes, got:", len(filtered))
t.Error("Expected 2 routes, got:", len(filtered))
}
// Check presence of route_01 and _03, matching prefix 123.

View File

@ -19,7 +19,7 @@ func (err *ErrValidationFailed) Error() string {
return err.Reason
}
// NewErrMissingParam returns a new error idicating
// NewErrMissingParam returns a new error indicating
// a missing query parameter.
func NewErrMissingParam(key string) *ErrValidationFailed {
return &ErrValidationFailed{
@ -28,12 +28,12 @@ func NewErrMissingParam(key string) *ErrValidationFailed {
}
}
// NewErrAmbigousParam returns an ErrValidationFailed,
// indicating that the parameter was ambigous.
func NewErrAmbigousParam(key string) *ErrValidationFailed {
// NewErrAmbiguousParam returns an ErrValidationFailed,
// indicating that the parameter was ambiguous.
func NewErrAmbiguousParam(key string) *ErrValidationFailed {
return &ErrValidationFailed{
Param: key,
Reason: fmt.Sprintf("query parameter %s is ambigous", key),
Reason: fmt.Sprintf("query parameter %s is ambiguous", key),
}
}
@ -79,7 +79,7 @@ func validateQueryString(req *http.Request, key string) (string, error) {
}
if len(values) != 1 {
return "", NewErrAmbigousParam(key)
return "", NewErrAmbiguousParam(key)
}
value := values[0]

23
pkg/http/metrics.go Normal file
View File

@ -0,0 +1,23 @@
package http
import (
"context"
"log"
"github.com/julienschmidt/httprouter"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func (s *Server) registerMetrics(
ctx context.Context,
router *httprouter.Router,
) error {
if s.cfg.Server.EnableMetrics == false {
return nil
}
log.Println("Metrics enabled and available on: /metrics")
router.Handler("GET", "/metrics", promhttp.Handler())
return nil
}

View File

@ -8,10 +8,11 @@ import (
"net/http"
"time"
"github.com/alice-lg/alice-lg/pkg/config"
"github.com/alice-lg/alice-lg/pkg/store"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/julienschmidt/httprouter"
"github.com/alice-lg/alice-lg/pkg/config"
"github.com/alice-lg/alice-lg/pkg/store"
)
// Server provides the HTTP server for the API
@ -51,6 +52,9 @@ func (s *Server) Start(ctx context.Context) {
if err := s.apiRegisterEndpoints(router); err != nil {
log.Fatal(err)
}
if err := s.registerMetrics(ctx, router); err != nil {
log.Fatal(err)
}
httpTimeout := time.Duration(s.cfg.Server.HTTPTimeout) * time.Second
log.Println("Web server HTTP timeout set to:", httpTimeout)

View File

@ -9,7 +9,7 @@ package http
directory will be included in the frontends HTML.
Additional files can be added in subdirectories.
These are served aswell and can be used for additional
These are served as well and can be used for additional
assets. (E.g. a logo)
*/
@ -108,7 +108,7 @@ func (t *Theme) StylesheetIncludes() string {
return strings.Join(includes, "\n")
}
// Scripts retrieve a list of includeable javascipts
// Scripts retrieve a list of includeable javascripts
func (t *Theme) Scripts() []string {
return t.listIncludes(".js")
}

View File

@ -13,7 +13,7 @@ import (
)
// Web Client
// Handle assets and client app preprarations
// Handle assets and client app preparations
// Prepare client HTML:
// Set paths and add version to assets.
@ -76,7 +76,7 @@ func (s *Server) webRegisterAssets(
io.WriteString(res, themedHTML)
})
// ...and all alice related paths aswell
// ...and all alice related paths as well
alicePaths := []string{
"/routeservers/*path",
"/search/*path",

View File

@ -57,7 +57,7 @@ func (p *StringListPool) Acquire(list []string) []string {
return p.root.value
}
// Make idenfier list
// Make identifier list
id := make([]int, len(list))
for i, s := range list {
// Resolve string value into int

View File

@ -96,7 +96,7 @@ func parseCacheStatus(
status := api.CacheStatus{
CachedAt: cachedAtTime,
// We ommit OrigTTL for now...
// We omit OrigTTL for now...
}
return status, nil
@ -286,7 +286,7 @@ func parseBgpCommunities(data interface{}) []api.Community {
return communities
}
// Extract extended communtieis
// Extract extended communities
func parseExtBgpCommunities(data interface{}) []api.ExtCommunity {
communities := []api.ExtCommunity{}
ldata, ok := data.([]interface{})

View File

@ -51,7 +51,7 @@ func Test_ParseApiStatus(t *testing.T) {
return
}
// Assertations
// Assertions
if apiStatus.Version != "1.7.11" {
t.Error("Expected version: 1.7.11, got:", apiStatus.Version)
}
@ -106,7 +106,7 @@ func Test_RoutesParsing(t *testing.T) {
t.Error("Expected parsed routes to be 1, not:", len(routes))
}
// TODO: addo more tests
// TODO: add more tests
}
func Test_ParseServerTime(t *testing.T) {

View File

@ -30,7 +30,7 @@ type GenericBirdwatcher struct {
routesRequiredCache *caches.RoutesCache
routesNotExportedCache *caches.RoutesCache
// Mutices:
// Mutexes:
routesFetchMutex *LockMap
}
@ -205,7 +205,7 @@ func (b *GenericBirdwatcher) ExpireCaches() int {
return count
}
// Status retrievs the current backend status
// Status retrieves the current backend status
func (b *GenericBirdwatcher) Status(ctx context.Context) (*api.StatusResponse, error) {
bird, err := b.client.GetJSON(ctx, "/status")
if err != nil {

View File

@ -57,7 +57,7 @@ func NewExtendedNexthopCapability(a *bgp.CapExtendedNexthop) *api.ExtendedNextho
}
}
// NewGracefulRestartCapability creates a new graceful resetart capabilty
// NewGracefulRestartCapability creates a new graceful restart capability
func NewGracefulRestartCapability(a *bgp.CapGracefulRestart) *api.GracefulRestartCapability {
tuples := make([]*api.GracefulRestartCapabilityTuple, 0, len(a.Tuples))
for _, t := range a.Tuples {
@ -73,7 +73,7 @@ func NewGracefulRestartCapability(a *bgp.CapGracefulRestart) *api.GracefulRestar
}
}
// NewFourOctetASNumberCapability creates new 32bit ASN capabiliy
// NewFourOctetASNumberCapability creates new 32bit ASN capability
func NewFourOctetASNumberCapability(a *bgp.CapFourOctetASNumber) *api.FourOctetASNumberCapability {
return &api.FourOctetASNumberCapability{
As: a.CapValue,

View File

@ -52,7 +52,7 @@ func (gobgp *GoBGP) lookupNeighbor(
return nil, fmt.Errorf("could not lookup neighbor")
}
// GetNeighbors retrievs all neighbors and returns
// GetNeighbors retrieves all neighbors and returns
// a list of peers.
func (gobgp *GoBGP) GetNeighbors(
ctx context.Context,

View File

@ -93,7 +93,7 @@ func (gobgp *GoBGP) ExpireCaches() int {
return count
}
// NeighborsStatus retrievs all status information
// NeighborsStatus retrieves all status information
// for all peers on the RS.
func (gobgp *GoBGP) NeighborsStatus(
ctx context.Context,
@ -130,12 +130,13 @@ func (gobgp *GoBGP) NeighborsStatus(
_resp.Peer.Timers.State.Uptime.Seconds,
int64(_resp.Peer.Timers.State.Uptime.Nanos)))
}
response.Neighbors = append(response.Neighbors, &ns)
}
return &response, nil
}
// Status retrievs the routers status
// Status retrieves the routers status
func (gobgp *GoBGP) Status(
ctx context.Context,
) (*api.StatusResponse, error) {
@ -154,7 +155,7 @@ func (gobgp *GoBGP) Status(
return &response, nil
}
// Neighbors retrievs a list of neighbors
// Neighbors retrieves a list of neighbors
func (gobgp *GoBGP) Neighbors(
ctx context.Context,
) (*api.NeighborsResponse, error) {

View File

@ -81,7 +81,7 @@ func (src *BgplgdSource) ShowNeighborsSummaryRequest(
return http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
}
// ShowNeighborRIBRequest retrives the routes accepted from the neighbor
// ShowNeighborRIBRequest retrieves the routes accepted from the neighbor
// identified by bgp-id.
func (src *BgplgdSource) ShowNeighborRIBRequest(
ctx context.Context,
@ -129,7 +129,7 @@ func (src *BgplgdSource) Status(ctx context.Context) (*api.StatusResponse, error
return response, nil
}
// Neighbors retrievs a full list of all neighbors
// Neighbors retrieves a full list of all neighbors
func (src *BgplgdSource) Neighbors(
ctx context.Context,
) (*api.NeighborsResponse, error) {
@ -180,7 +180,7 @@ func (src *BgplgdSource) Neighbors(
return response, nil
}
// NeighborsSummary retrievs list of neighbors, which
// NeighborsSummary retrieves list of neighbors, which
// might lack details like with number of rejected routes.
// It is much faster though.
func (src *BgplgdSource) NeighborsSummary(
@ -227,8 +227,8 @@ func (src *BgplgdSource) NeighborsSummary(
return response, nil
}
// NeighborsStatus retrives the status summary
// for all neightbors
// NeighborsStatus retrieves the status summary
// for all neighbors
func (src *BgplgdSource) NeighborsStatus(
ctx context.Context,
) (*api.NeighborsStatusResponse, error) {
@ -411,7 +411,7 @@ func (src *BgplgdSource) RoutesFiltered(
return response, nil
}
// RoutesNotExported retrievs the routes not exported
// RoutesNotExported retrieves the routes not exported
// from the rs for a neighbor.
func (src *BgplgdSource) RoutesNotExported(
ctx context.Context,
@ -428,7 +428,7 @@ func (src *BgplgdSource) RoutesNotExported(
return response, nil
}
// AllRoutes retrievs the entire RIB from the source. This is never
// AllRoutes retrieves the entire RIB from the source. This is never
// cached as it is processed by the store.
func (src *BgplgdSource) AllRoutes(
ctx context.Context,

View File

@ -43,7 +43,7 @@ func decodeNeighbor(n interface{}) (*api.Neighbor, error) {
prefixes := decoders.MapGet(stats, "prefixes", map[string]interface{}{})
neighbor := &api.Neighbor{
// ID: decoders.MapGetString(nb, "remote_addr", "invalid_id"),
ID: decoders.MapGetString(nb, "remote_addr", "invalid_id"),
Address: decoders.MapGetString(nb, "remote_addr", "invalid_address"),
ASN: decoders.IntFromString(decoders.MapGetString(nb, "remote_as", ""), -1),
State: decodeState(decoders.MapGetString(nb, "state", "unknown")),
@ -70,7 +70,7 @@ func describeNeighbor(nb interface{}) string {
return fmt.Sprintf("PEER AS%s %s", asn, addr)
}
// decodeNeighbors retrievs neighbors data from
// decodeNeighbors retrieves neighbors data from
// the bgpctl response.
func decodeNeighbors(res map[string]interface{}) (api.Neighbors, error) {
nbs := decoders.MapGet(res, "neighbors", nil)
@ -92,7 +92,7 @@ func decodeNeighbors(res map[string]interface{}) (api.Neighbors, error) {
return all, nil
}
// decodeNeighborsStatus retrievs a neighbors summary
// decodeNeighborsStatus retrieves a neighbors summary
// and decodes the status.
func decodeNeighborsStatus(res map[string]interface{}) (api.NeighborsStatus, error) {
nbs := decoders.MapGet(res, "neighbors", nil)
@ -234,7 +234,7 @@ func decodeCommunities(c interface{}) api.Communities {
return comms
}
// decodeExtendedCommunities decodes extended communties
// decodeExtendedCommunities decodes extended communities
// into a list of (str, int, int).
func decodeExtendedCommunities(c interface{}) api.ExtCommunities {
details := decoders.StringList(c)

View File

@ -20,7 +20,7 @@ const (
)
// StateServerSource implements the OpenBGPD source for Alice.
// It is intendet to consume structured bgpctl output
// It is intended to consume structured bgpctl output
// queried over HTTP using the:
//
// openbgpd-state-server
@ -93,7 +93,7 @@ func (src *StateServerSource) ShowNeighborsSummaryRequest(
return http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
}
// ShowNeighborRIBRequest retrives the routes accepted from the neighbor
// ShowNeighborRIBRequest retrieves the routes accepted from the neighbor
// identified by bgp-id.
func (src *StateServerSource) ShowNeighborRIBRequest(
ctx context.Context,
@ -153,7 +153,7 @@ func (src *StateServerSource) Status(
return response, nil
}
// Neighbors retrievs a full list of all neighbors
// Neighbors retrieves a full list of all neighbors
func (src *StateServerSource) Neighbors(
ctx context.Context,
) (*api.NeighborsResponse, error) {
@ -250,8 +250,8 @@ func (src *StateServerSource) NeighborsSummary(
return response, nil
}
// NeighborsStatus retrives the status summary
// for all neightbors
// NeighborsStatus retrieves the status summary
// for all neighbors
func (src *StateServerSource) NeighborsStatus(
ctx context.Context,
) (*api.NeighborsStatusResponse, error) {
@ -430,7 +430,7 @@ func (src *StateServerSource) RoutesFiltered(
return response, nil
}
// RoutesNotExported retrievs the routes not exported
// RoutesNotExported retrieves the routes not exported
// from the rs for a neighbor.
func (src *StateServerSource) RoutesNotExported(
ctx context.Context,
@ -447,7 +447,7 @@ func (src *StateServerSource) RoutesNotExported(
return response, nil
}
// AllRoutes retrievs the entire RIB from the source. This is never
// AllRoutes retrieves the entire RIB from the source. This is never
// cached as it is processed by the store.
func (src *StateServerSource) AllRoutes(
ctx context.Context,

View File

@ -17,7 +17,7 @@ type NeighborsBackend struct {
neighbors *sync.Map
}
// NewNeighborsBackend instanciates a new in memory
// NewNeighborsBackend instantiates a new in memory
// neighbors backend.
func NewNeighborsBackend() *NeighborsBackend {
return &NeighborsBackend{
@ -79,7 +79,7 @@ func (b *NeighborsBackend) GetNeighborsMapAt(
return result, nil
}
// CountNeighborsAt retrievs the number of neighbors
// CountNeighborsAt retrieves the number of neighbors
// at this source.
func (b *NeighborsBackend) CountNeighborsAt(
ctx context.Context,

View File

@ -112,7 +112,7 @@ func (r *RoutesBackend) FindByPrefix(
return false
}
for _, route := range rs.(api.LookupRoutes) {
// Naiive string filtering:
// Naive string filtering:
if hasPrefix && !strings.HasPrefix(strings.ToLower(route.Network), prefix) {
continue
}

View File

@ -58,7 +58,7 @@ func (m *Manager) Start(ctx context.Context) {
}
// Status retrieves the current schema version
// and checks if migrated. In case an error occures,
// and checks if migrated. In case an error occurs,
// it will be included in the result.
func (m *Manager) Status(ctx context.Context) *Status {
status := &Status{}
@ -82,7 +82,7 @@ func (m *Manager) Status(ctx context.Context) *Status {
return status
}
// Migrate applies the database intialisation script if required.
// Migrate applies the database initialization script if required.
func (m *Manager) Migrate(ctx context.Context) error {
s := m.Status(ctx)
if s.Migrated {

View File

@ -11,7 +11,7 @@ import (
)
// StartHousekeeping is a background task flushing
// memory and expireing caches.
// memory and expiring caches.
func StartHousekeeping(ctx context.Context, cfg *config.Config) {
for {

190
pkg/store/metrics.go Normal file
View File

@ -0,0 +1,190 @@
package store
import (
"context"
"log"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
)
type metrics struct {
neighborsStore *NeighborsStore
neighborInfo *prometheus.GaugeVec
neighborUptime *prometheus.GaugeVec
routesReceived *prometheus.GaugeVec
routesFiltered *prometheus.GaugeVec
routesPreferred *prometheus.GaugeVec
routesAccepted *prometheus.GaugeVec
}
// Initialize
func initMetrics(s *NeighborsStore) *metrics {
log.Println("[metrics] Initializing export.")
labels := []string{
// The route server ID
"route_server_id",
"route_server_name",
"route_server_group",
"neighbor_id",
"neighbor_description",
"neighbor_asn",
"neighbor_address",
}
neighborInfo := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "neighbor_info",
Help: "Information about the neighbor including the state",
},
append(labels, "neighbor_state"),
)
neighborUptime := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "neighbor_uptime_seconds_total",
Help: "The uptime of a neighbor on a route server in seconds",
},
labels,
)
routesReceived := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "routes_received",
Help: "Total number of routes received by a route server for a given neighbor",
},
labels,
)
routesFiltered := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "routes_filtered",
Help: "Total number of routes filtered by a route server for a given neighbor",
},
labels,
)
routesPreferred := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "routes_preferred",
Help: "Total number of routes preferred by a route server for a given neighbor",
},
labels,
)
routesAccepted := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "routes_accepted",
Help: "Total number of routes accepted by a route server for a given neighbor",
},
labels,
)
prometheus.MustRegister(neighborInfo)
prometheus.MustRegister(neighborUptime)
prometheus.MustRegister(routesReceived)
prometheus.MustRegister(routesFiltered)
prometheus.MustRegister(routesPreferred)
prometheus.MustRegister(routesAccepted)
return &metrics{
neighborsStore: s,
neighborInfo: neighborInfo,
neighborUptime: neighborUptime,
routesReceived: routesReceived,
routesFiltered: routesFiltered,
routesPreferred: routesPreferred,
routesAccepted: routesAccepted,
}
}
// Update the metrics with information from the store.
func (m *metrics) update(ctx context.Context) error {
rsIDs := m.neighborsStore.sources.GetSourceIDs()
// For all route servers, fetch neighbors list and
// update statistics.
for _, rsID := range rsIDs {
if !m.neighborsStore.IsInitialized(rsID) {
continue // No data from RS yet
}
rs := m.neighborsStore.sources.Get(rsID)
neighbors, err := m.neighborsStore.GetNeighborsAt(ctx, rsID)
if err != nil {
return err
}
// Get neighbors
for _, neighbor := range neighbors {
m.neighborInfo.With(prometheus.Labels{
"route_server_id": rs.ID,
"route_server_name": rs.Name,
"route_server_group": rs.Group,
"neighbor_id": neighbor.ID,
"neighbor_description": neighbor.Description,
"neighbor_asn": strconv.Itoa(neighbor.ASN),
"neighbor_address": neighbor.Address,
"neighbor_state": neighbor.State,
}).Set(1.0)
labels := prometheus.Labels{
"route_server_id": rs.ID,
"route_server_name": rs.Name,
"route_server_group": rs.Group,
"neighbor_id": neighbor.ID,
"neighbor_description": neighbor.Description,
"neighbor_asn": strconv.Itoa(neighbor.ASN),
"neighbor_address": neighbor.Address,
}
m.neighborUptime.
With(labels).
Set(neighbor.Uptime.Seconds())
m.routesReceived.
With(labels).
Set(float64(neighbor.RoutesReceived))
m.routesFiltered.
With(labels).
Set(float64(neighbor.RoutesFiltered))
m.routesPreferred.
With(labels).
Set(float64(neighbor.RoutesPreferred))
m.routesAccepted.
With(labels).
Set(float64(neighbor.RoutesAccepted))
}
}
return nil
}
// Startmetrics registers the metrics and starts a
// periodical refresh.
func StartMetrics(
ctx context.Context,
neighborsStore *NeighborsStore,
) {
m := initMetrics(neighborsStore)
// Every 5 second, update the metrics
log.Println("[metrics] Starting refresh.")
for {
select {
case <-ctx.Done():
return
case <-time.After(time.Second * 5):
err := m.update(ctx)
if err != nil {
log.Println(
"[metrics] Error while updating:", err)
}
}
}
}

View File

@ -108,7 +108,7 @@ func (s *NeighborsStore) Start(ctx context.Context) {
}
}
// GetStatus retrievs the status for a route server
// GetStatus retrieves the status for a route server
// identified by sourceID.
func (s *NeighborsStore) GetStatus(sourceID string) (*Status, error) {
return s.sources.GetStatus(sourceID)
@ -150,7 +150,7 @@ func (s *NeighborsStore) safeUpdateSource(ctx context.Context, id string) {
}
if err := s.sources.LockSource(id); err != nil {
log.Println("Cloud not start neighbor refresh:", err)
log.Println("[neighbors store] could not start neighbor refresh:", err)
return
}
@ -165,15 +165,15 @@ func (s *NeighborsStore) safeUpdateSource(ctx context.Context, id string) {
defer func() {
if err := recover(); err != nil {
log.Println(
"Recovering after failed neighbors refresh of",
srcName, "from:", err)
"[neighbors store] recovering after failed neighbors refresh from",
srcName, "with error:", err)
s.sources.RefreshError(id, err)
}
}()
if err := s.updateSource(ctx, src, id); err != nil {
log.Println(
"Refeshing neighbors of", srcName, "failed:", err)
"[neighbors store] refreshing neighbors from", srcName, "failed:", err)
s.sources.RefreshError(id, err)
}
@ -181,7 +181,7 @@ func (s *NeighborsStore) safeUpdateSource(ctx context.Context, id string) {
if err != nil {
log.Println(err)
} else {
log.Println("Refreshed neighbors of", srcName, "in", status.LastRefreshDuration)
log.Println("[neighbors store] refreshed neighbors from", srcName, "in", status.LastRefreshDuration)
}
}
@ -332,7 +332,7 @@ func (s *NeighborsStore) Stats(
ncount, err := s.backend.CountNeighborsAt(ctx, sourceID)
if err != nil {
if !errors.Is(err, sources.ErrSourceNotFound) {
log.Println("error during neighbor count:", err)
log.Println("[neighbors store] error during neighbor count:", err)
}
}
totalNeighbors += ncount
@ -381,7 +381,7 @@ func (s *NeighborsStore) Status(ctx context.Context) *api.StoreStatus {
func (s *NeighborsStore) SourceCachedAt(sourceID string) time.Time {
status, err := s.sources.GetStatus(sourceID)
if err != nil {
log.Println("error while getting source cached at:", err)
log.Println("[neighbors store] error while getting source cached at:", err)
return time.Time{}
}
return status.LastRefresh

View File

@ -142,7 +142,7 @@ func (s *RoutesStore) safeUpdateSource(ctx context.Context, id string) {
}
if err := s.sources.LockSource(id); err != nil {
log.Println("Cloud not start routes refresh:", err)
log.Println("[routes store] could not start routes refresh:", err)
return
}
@ -153,28 +153,28 @@ func (s *RoutesStore) safeUpdateSource(ctx context.Context, id string) {
src := s.sources.Get(id)
srcName := s.sources.GetName(id)
log.Println("[routes store] begin routes refresh of:", srcName)
log.Println("[routes store] begin routes refresh from", srcName)
// Prepare for impact.
defer func() {
if err := recover(); err != nil {
log.Println(
"Recovering after failed routes refresh of",
src.Name, "from:", err)
"[routes store] recovering after failed routes refresh from",
src.Name, "with error:", err)
s.sources.RefreshError(id, err)
}
}()
if err := s.updateSource(ctx, src); err != nil {
log.Println(
"Refeshing routes of", src.Name, "failed:", err)
"[routes store] refreshing routes from", src.Name, "failed:", err)
s.sources.RefreshError(id, err)
} else {
status, err := s.sources.GetStatus(id)
if err != nil {
log.Println(err)
} else {
log.Println("Refreshed routes of", srcName, "in", status.LastRefreshDuration)
log.Println("[routes store] refreshed routes from", srcName, "in", status.LastRefreshDuration)
}
}
}
@ -194,7 +194,7 @@ func (s *RoutesStore) updateSource(
return err
}
log.Println("[routes store] finished fetching routes dump from RS", src.Name)
log.Println("[routes store] finished fetching routes dump from", src.Name)
neighbors, err := s.neighbors.GetNeighborsMapAt(ctx, src.ID)
if err != nil {
@ -203,7 +203,7 @@ func (s *RoutesStore) updateSource(
log.Println(
"[routes store] retrieved", len(res.Imported),
"accepted and", len(res.Filtered), "filtered routes for:", src.Name)
"accepted and", len(res.Filtered), "filtered routes from", src.Name)
// Prepare imported routes for lookup
srcRS := &api.LookupRouteServer{
@ -214,11 +214,11 @@ func (s *RoutesStore) updateSource(
filtered := res.Filtered.ToLookupRoutes("filtered", srcRS, neighbors)
lookupRoutes := append(imported, filtered...)
log.Println("[routes store] importing", len(lookupRoutes), "into store from", src.Name)
log.Println("[routes store] importing", len(lookupRoutes), "routes into store from", src.Name)
if err = s.backend.SetRoutes(ctx, src.ID, lookupRoutes); err != nil {
return err
}
log.Println("[routes store] import success")
log.Println("[routes store] successfully imported", len(lookupRoutes), "routes into store from", src.Name)
return s.sources.RefreshSuccess(src.ID)
}
@ -277,7 +277,7 @@ func (s *RoutesStore) Stats(ctx context.Context) *api.RoutesStoreStats {
for _, sourceID := range s.sources.GetSourceIDs() {
status, err := s.sources.GetStatus(sourceID)
if err != nil {
log.Println("error while getting source status:", err)
log.Println("[routes store] error while getting source status:", err)
continue
}
@ -285,7 +285,7 @@ func (s *RoutesStore) Stats(ctx context.Context) *api.RoutesStoreStats {
nImported, nFiltered, err := s.backend.CountRoutesAt(ctx, sourceID)
if err != nil {
if !errors.Is(err, sources.ErrSourceNotFound) {
log.Println("error during routes count:", err)
log.Println("[routes store] error during routes count:", err)
}
}

View File

@ -190,7 +190,7 @@ func (s *SourcesStore) ShouldRefresh(
}
if status.State == StateError {
// The refresh interval in the config is ok if the
// success case. When an error occures it is desirable
// success case. When an error occurs it is desirable
// to retry sooner, without spamming the server.
nextRefresh = status.LastRefresh.Add(10 * time.Second)
}
@ -202,7 +202,7 @@ func (s *SourcesStore) ShouldRefresh(
return true // Go for it
}
// CachedAt retrievs the oldest refresh time
// CachedAt retrieves the oldest refresh time
// from all sources. All data is then guaranteed to be older
// than the CachedAt date.
func (s *SourcesStore) CachedAt(ctx context.Context) time.Time {

View File

@ -14,11 +14,11 @@ func ContainsCi(s, substr string) bool {
)
}
// SerializeReasons asserts the bgp communitiy parts are
// SerializeReasons asserts the bgp community parts are
// actually strings, because there are no such things as
// integers as keys in json.
// Serialization of this is undefined behaviour, so we
// keep these interallybut provide a string as a key for
// keep these internally but provide a string as a key for
// serialization
func SerializeReasons(reasons map[int]string) map[string]string {
res := make(map[string]string)

View File

@ -76,7 +76,7 @@ const Routing = () => (
/**
* The application main entry point.
* Instanciate global providers and the router.
* Instantiate global providers and the router.
*/
const Main = () => {
return (

View File

@ -2,7 +2,7 @@
import moment from 'moment'
/**
* Render the formated 'absolute' time when given a
* Render the formatted 'absolute' time when given a
* relative timestamp (in nanoseconds).
*
* The timestamp is the duration from now to the absolute

View File

@ -1,6 +1,6 @@
/**
* Errors Component renders a stack of dismissable errors.
* Errors Component renders a stack of dismissible errors.
*/
import { FontAwesomeIcon }
from '@fortawesome/react-fontawesome';
@ -25,7 +25,7 @@ const infoFromError = (error) => {
/**
* Error renders a single dismissable error
* Error renders a single dismissible error
*/
const Error = ({error, onDismiss}) => {
const routeServers = useRouteServers();

View File

@ -116,7 +116,7 @@ const GroupSelect = ({groups, selected, onSelect}) => {
<GroupSelectOption key={group} group={group} onSelect={selectGroup} />
);
// Partition options into n coulumns with a maximum
// Partition options into n columns with a maximum
// of 10 rows per column.
const maxRows = 10;
const n = Math.ceil(options.length / maxRows);

View File

@ -19,11 +19,17 @@ const Sidebar = () => {
<div className="sidebar-header">
<div className="logo">
<Link to='/'>
<i>{/* Theme compatbility */}
<FontAwesomeIcon
className="logo-icon"
icon={faCloud} size="lg" transform="grow-11" />
</i>
<span>
<Content id="header.logo">
<i>
<FontAwesomeIcon
className="logo-icon"
icon={faCloud}
size="lg"
transform="grow-11" />
</i>
</Content>
</span>
</Link>
</div>
<div className="title">

View File

@ -87,9 +87,9 @@ const Neighbors = () => {
let s = n.state.toLowerCase();
if (s.includes("up") || s.includes("established") ) {
up.push(n);
} else if (s.includes("down")) {
} else if (s.includes("down") || s.includes("start") || s.includes("active") || s.includes("connect")) {
down.push(n);
} else if (s.includes("start") || s.includes("active")) {
} else if (s.includes("idle")) {
idle.push(n);
} else {
console.error("Couldn't classify neighbor by state:", n);

View File

@ -123,14 +123,14 @@ const Section = ({state}) => {
sectionTitle = 'BGP Sessions Established';
sectionCls += 'established ';
break;
case 'idle':
sectionTitle = 'Idle BGP Sessions';
sectionCls += 'idle ';
break;
case 'down':
sectionTitle = 'BGP Sessions Down';
sectionCls += 'down ';
break;
case 'start':
sectionTitle = 'BGP Sessions Start';
sectionCls += '';
break;
default:
}
return (<p className={sectionCls}>{sectionTitle}</p>);
@ -262,7 +262,7 @@ const NeighborColumn = ({neighbor, column}) => {
"Description": ColDescription,
};
// For openbgpd the value is ommitted
// For openbgpd the value is omitted
if (rs.type === "openbgpd") {
widgets["routes_not_exported"] = ColNotAvailable;
}

View File

@ -30,7 +30,7 @@ const QuickLinks = () => {
const filtered = useRoutesFiltered();
const notExported = useRoutesNotExported();
const locRecevied = useMemo(() => ({...location, hash: "routes-received"}), [
const locReceived = useMemo(() => ({...location, hash: "routes-received"}), [
location,
]);
const locFiltered = useMemo(() => ({...location, hash: "routes-filtered"}), [
@ -57,7 +57,7 @@ const QuickLinks = () => {
<Link to={locFiltered}>Filtered</Link></li>}
{ showReceived &&
<li className="received">
<Link to={locRecevied}>Accepted</Link></li>}
<Link to={locReceived}>Accepted</Link></li>}
{ showNotExported &&
<li className="not-exported">
<Link to={locNotExported}>Not Exported</Link></li>}

View File

@ -10,7 +10,7 @@ import { Modal
, ModalFooter
}
from 'app/components/modal/Modal';
import BgpCommunitiyLabel
import BgpCommunityLabel
from 'app/components/routes/BgpCommunityLabel';
import { RouteAgeDetails }
from 'app/components/routes/Age';
@ -78,21 +78,21 @@ const RouteDetailsModal = () => {
<tr>
<th>Communities:</th>
<td>
{communities.map((c) => <BgpCommunitiyLabel community={c} key={communityKey(c)} />)}
{communities.map((c) => <BgpCommunityLabel community={c} key={communityKey(c)} />)}
</td>
</tr>}
{extCommunities.length > 0 &&
<tr>
<th>Ext. Communities:</th>
<td>
{extCommunities.map((c) => <BgpCommunitiyLabel community={c} key={communityKey(c)} />)}
{extCommunities.map((c) => <BgpCommunityLabel community={c} key={communityKey(c)} />)}
</td>
</tr>}
{largeCommunities.length > 0 &&
<tr>
<th>Large Communities:</th>
<td>
{largeCommunities.map((c) => <BgpCommunitiyLabel community={c} key={communityKey(c)} />)}
{largeCommunities.map((c) => <BgpCommunityLabel community={c} key={communityKey(c)} />)}
</td>
</tr>}
</tbody>

View File

@ -117,7 +117,7 @@ const RoutesNotExported = createRoutesSet(
/**
* Show a button to load routes not exported on demand.
* IF config states loading routes shoud be done automatically
* IF config states loading routes should be done automatically
* update the query parameter.
*/
const RoutesNotExportedRequest = () => {

View File

@ -63,7 +63,7 @@ const RpkiIndicator = ({route}) => {
}
// RPKI INVALID
// Depending on the configration this can either be a
// Depending on the configuration this can either be a
// single flag or a range with a given reason.
let rpkiInvalidReason = 0;
for (const invalid of rpkiInvalid) {

View File

@ -19,9 +19,9 @@ export const useErrorHandler = () => {
};
// Unfortunatley this does not really act as an error
// Unfortunately this does not really act as an error
// boundary. But we need to catch http errors from axios.
// Those are not cought using the ErrorBoundary approach.
// Those are not caught using the ErrorBoundary approach.
export const ErrorsProvider = ({children}) => {
const [errors, setErrors] = useState([]);

View File

@ -11,8 +11,8 @@ import { useQuery
/**
* usePageQuery retrievs the pagination
* query paramters and decodes the value
* usePageQuery retrieves the pagination
* query parameters and decodes the value
*/
export const usePageQuery = () => {
const [query] = useQuery({

View File

@ -207,7 +207,7 @@ const createRoutesProvider = (Context, useFetchRoutesState) => ({
/**
* RoutesReceivedProvider loads all routes recieved for a neighbor
* RoutesReceivedProvider loads all routes received for a neighbor
*/
export const RoutesReceivedProvider = createRoutesProvider(
RoutesReceivedContext,

View File

@ -61,7 +61,7 @@ const initialState = {
}
/**
* useSearchParam retrievs the query parameter
* useSearchParam retrieves the query parameter
*/
export const useSearchQuery = () => {
const [query] = useQuery({
@ -125,7 +125,7 @@ const decodeSearchResult = (result) => {
/**
* useSearchResult retrievs the url and returns the state
* useSearchResult retrieves the url and returns the state
*/
const useSearchResults = ({
query,
@ -207,7 +207,7 @@ export const SearchStatusProvider = ({children, api}) => {
/**
* RoutesSearchProvider provides routes received, filtered
* and not exportet.
* and not exported.
*/
export const RoutesSearchProvider = ({
children,

View File

@ -52,5 +52,9 @@
&.down {
color: red;
}
&.idle {
color: orange;
}
}