├── .gitignore ├── README.md ├── docker-compose.yml ├── generator.yml ├── prometheus.yml ├── run-generator.sh └── snmp.yml /.gitignore: -------------------------------------------------------------------------------- 1 | tmp/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ubiquiti Edgerouter metrics for Prometheus 2 | This repo contains both a generator specification for use with the Prometheus 3 | project's snmp_exporter generator tool and a generated configuration file, 4 | `snmp.yml`. The snmp exporter can be run in conjunction with a Prometheus server 5 | to fetch and store time series metrics for a Ubiquiti Edgerouter. These metrics 6 | can be in turn visualised (and alerted on) using Grafana. 7 | 8 | ## First use 9 | To get the exporter up and running as well as scraped by Prometheus, there are a 10 | few manual steps you'll need to perform: 11 | - Make sure SNMP is enabled on your Edgerouter and the community string is set 12 | - Modify `.edgerouter.auth.community` in `snmp.yml` to match your community 13 | string 14 | - Modify `.scrape_configs.0.static_configs.0.targets.0` in `prometheus.yml` to 15 | match the IP address of your Edgerouter 16 | 17 | Once these steps are complete, you can use `docker-compose up` to spin up the 18 | test environment. To test the exporter directly without using Prometheus Server, 19 | use the following command: 20 | ``` 21 | EDGEROUTER=192.168.1.1 # or whatever your Edgerouter's IP address is 22 | curl "http://localhost:9116/snmp?target=${EDGEROUTER_IP}&module=edgerouter" 23 | ``` 24 | 25 | ## Test environment 26 | `docker-compose.yml` in conjunction with `snmp.yml` and `prometheus.yml` 27 | describe how the pieces (SNMP exporter, Prometheus server, Edgerouter) are meant 28 | to interact with one another. Follow the above instructions to get this up and 29 | running properly. Adding a Grafana server to this spec would be trivial. 30 | 31 | ## Adding metrics 32 | Available metrics are detailed and stored directly on a given Edgerouter, in the 33 | `/usr/share/snmp/mibs/` directory. The ones listed in `generator.yml` were just 34 | those I found most useful when looking through these mib files, it's perfectly 35 | easy, if time consuming, to fetch these mib files and implement extra metrics by 36 | adding them to the `walk` list in `generator.yml`. Then use the config 37 | generator at 38 | in conjunction with the `mibs/` directory to generate a new `snmp.yml` file. 39 | 40 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | 4 | prometheus: 5 | image: prom/prometheus 6 | command: 7 | - --config.file=/prometheus.yml 8 | - --web.external-url=http://prometheus.l102.local 9 | volumes: 10 | - "./prometheus.yml:/prometheus.yml" 11 | ports: 12 | - 9090:9090 13 | 14 | snmp-exporter: 15 | image: prom/snmp-exporter 16 | command: 17 | - --config.file=/snmp.yml 18 | volumes: 19 | - "./snmp.yml:/snmp.yml:ro" 20 | ports: 21 | - 9116:9116 22 | 23 | -------------------------------------------------------------------------------- /generator.yml: -------------------------------------------------------------------------------- 1 | auths: 2 | public_v2: 3 | community: public 4 | version: 2 5 | modules: 6 | edgerouter: 7 | walk: 8 | - memTotalReal 9 | - memAvailReal 10 | - ssCpuRawIdle 11 | # host resource metrics 12 | - hrSystemUptime 13 | - hrSystemProcesses 14 | - hrSystemMaxProcesses 15 | - hrMemorySize 16 | - hrStorageSize 17 | - hrStorageUsed 18 | - hrProcessorLoad # non idle percent past minute 19 | # interface metrics 20 | - ifAdminStatus # 1=up,2=down,3=testing 21 | - ifOperStatus # 1=up,2=down,3=testing,4=unknown,5=dormant,6=notPresent,7=lowerLayerDown 22 | - ifLastChange 23 | - ifInDiscards 24 | - ifInErrors 25 | - ifOutDiscards 26 | - ifOutErrors 27 | - ifHCInOctets 28 | - ifHCOutOctets 29 | # tcp metrics 30 | - tcpMaxConn 31 | - tcpActiveOpens 32 | - tcpPassiveOpens 33 | - tcpEstabResets 34 | - tcpCurrEstab 35 | lookups: 36 | - source_indexes: [ifIndex] 37 | lookup: ifName 38 | -------------------------------------------------------------------------------- /prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | evaluation_interval: 30s 3 | scrape_interval: 30s 4 | scrape_timeout: 10s 5 | 6 | scrape_configs: 7 | - job_name: edgerouter 8 | static_configs: 9 | - targets: 10 | - 192.168.1.1 11 | metrics_path: /snmp 12 | params: 13 | module: 14 | - edgerouter 15 | relabel_configs: 16 | - source_labels: [__address__] 17 | target_label: __param_target 18 | - source_labels: [__param_target] 19 | target_label: instance 20 | - target_label: __address__ 21 | replacement: snmp-exporter:9116 22 | 23 | -------------------------------------------------------------------------------- /run-generator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | rm -rf tmp && mkdir -p tmp 4 | cp generator.yml tmp/ 5 | 6 | docker run -ti \ 7 | -v ${PATH_TO_MIBS}:/root/.snmp/mibs \ 8 | -v $PWD/tmp/:/opt/ \ 9 | snmp-generator generate 10 | 11 | -------------------------------------------------------------------------------- /snmp.yml: -------------------------------------------------------------------------------- 1 | # WARNING: This file was auto-generated using snmp_exporter generator, manual changes will be lost. 2 | auths: 3 | public_v2: 4 | community: public 5 | security_level: noAuthNoPriv 6 | auth_protocol: MD5 7 | priv_protocol: DES 8 | version: 2 9 | modules: 10 | edgerouter: 11 | walk: 12 | - 1.3.6.1.2.1.2.2.1.13 13 | - 1.3.6.1.2.1.2.2.1.14 14 | - 1.3.6.1.2.1.2.2.1.19 15 | - 1.3.6.1.2.1.2.2.1.20 16 | - 1.3.6.1.2.1.2.2.1.7 17 | - 1.3.6.1.2.1.2.2.1.8 18 | - 1.3.6.1.2.1.2.2.1.9 19 | - 1.3.6.1.2.1.25.2.3.1.5 20 | - 1.3.6.1.2.1.25.2.3.1.6 21 | - 1.3.6.1.2.1.25.3.3.1.2 22 | - 1.3.6.1.2.1.31.1.1.1.1 23 | - 1.3.6.1.2.1.31.1.1.1.10 24 | - 1.3.6.1.2.1.31.1.1.1.6 25 | get: 26 | - 1.3.6.1.2.1.25.1.1.0 27 | - 1.3.6.1.2.1.25.1.6.0 28 | - 1.3.6.1.2.1.25.1.7.0 29 | - 1.3.6.1.2.1.25.2.2.0 30 | - 1.3.6.1.2.1.6.4.0 31 | - 1.3.6.1.2.1.6.5.0 32 | - 1.3.6.1.2.1.6.6.0 33 | - 1.3.6.1.2.1.6.8.0 34 | - 1.3.6.1.2.1.6.9.0 35 | - 1.3.6.1.4.1.2021.11.53.0 36 | - 1.3.6.1.4.1.2021.4.5.0 37 | - 1.3.6.1.4.1.2021.4.6.0 38 | metrics: 39 | - name: ifInDiscards 40 | oid: 1.3.6.1.2.1.2.2.1.13 41 | type: counter 42 | help: The number of inbound packets which were chosen to be discarded even though 43 | no errors had been detected to prevent their being deliverable to a higher-layer 44 | protocol - 1.3.6.1.2.1.2.2.1.13 45 | indexes: 46 | - labelname: ifIndex 47 | type: gauge 48 | lookups: 49 | - labels: 50 | - ifIndex 51 | labelname: ifName 52 | oid: 1.3.6.1.2.1.31.1.1.1.1 53 | type: DisplayString 54 | - name: ifInErrors 55 | oid: 1.3.6.1.2.1.2.2.1.14 56 | type: counter 57 | help: For packet-oriented interfaces, the number of inbound packets that contained 58 | errors preventing them from being deliverable to a higher-layer protocol - 59 | 1.3.6.1.2.1.2.2.1.14 60 | indexes: 61 | - labelname: ifIndex 62 | type: gauge 63 | lookups: 64 | - labels: 65 | - ifIndex 66 | labelname: ifName 67 | oid: 1.3.6.1.2.1.31.1.1.1.1 68 | type: DisplayString 69 | - name: ifOutDiscards 70 | oid: 1.3.6.1.2.1.2.2.1.19 71 | type: counter 72 | help: The number of outbound packets which were chosen to be discarded even 73 | though no errors had been detected to prevent their being transmitted - 1.3.6.1.2.1.2.2.1.19 74 | indexes: 75 | - labelname: ifIndex 76 | type: gauge 77 | lookups: 78 | - labels: 79 | - ifIndex 80 | labelname: ifName 81 | oid: 1.3.6.1.2.1.31.1.1.1.1 82 | type: DisplayString 83 | - name: ifOutErrors 84 | oid: 1.3.6.1.2.1.2.2.1.20 85 | type: counter 86 | help: For packet-oriented interfaces, the number of outbound packets that could 87 | not be transmitted because of errors - 1.3.6.1.2.1.2.2.1.20 88 | indexes: 89 | - labelname: ifIndex 90 | type: gauge 91 | lookups: 92 | - labels: 93 | - ifIndex 94 | labelname: ifName 95 | oid: 1.3.6.1.2.1.31.1.1.1.1 96 | type: DisplayString 97 | - name: ifAdminStatus 98 | oid: 1.3.6.1.2.1.2.2.1.7 99 | type: gauge 100 | help: The desired state of the interface - 1.3.6.1.2.1.2.2.1.7 101 | indexes: 102 | - labelname: ifIndex 103 | type: gauge 104 | lookups: 105 | - labels: 106 | - ifIndex 107 | labelname: ifName 108 | oid: 1.3.6.1.2.1.31.1.1.1.1 109 | type: DisplayString 110 | enum_values: 111 | 1: up 112 | 2: down 113 | 3: testing 114 | - name: ifOperStatus 115 | oid: 1.3.6.1.2.1.2.2.1.8 116 | type: gauge 117 | help: The current operational state of the interface - 1.3.6.1.2.1.2.2.1.8 118 | indexes: 119 | - labelname: ifIndex 120 | type: gauge 121 | lookups: 122 | - labels: 123 | - ifIndex 124 | labelname: ifName 125 | oid: 1.3.6.1.2.1.31.1.1.1.1 126 | type: DisplayString 127 | enum_values: 128 | 1: up 129 | 2: down 130 | 3: testing 131 | 4: unknown 132 | 5: dormant 133 | 6: notPresent 134 | 7: lowerLayerDown 135 | - name: ifLastChange 136 | oid: 1.3.6.1.2.1.2.2.1.9 137 | type: gauge 138 | help: The value of sysUpTime at the time the interface entered its current operational 139 | state - 1.3.6.1.2.1.2.2.1.9 140 | indexes: 141 | - labelname: ifIndex 142 | type: gauge 143 | lookups: 144 | - labels: 145 | - ifIndex 146 | labelname: ifName 147 | oid: 1.3.6.1.2.1.31.1.1.1.1 148 | type: DisplayString 149 | - name: hrSystemUptime 150 | oid: 1.3.6.1.2.1.25.1.1 151 | type: gauge 152 | help: The amount of time since this host was last initialized - 1.3.6.1.2.1.25.1.1 153 | - name: hrSystemProcesses 154 | oid: 1.3.6.1.2.1.25.1.6 155 | type: gauge 156 | help: The number of process contexts currently loaded or running on this system. 157 | - 1.3.6.1.2.1.25.1.6 158 | - name: hrSystemMaxProcesses 159 | oid: 1.3.6.1.2.1.25.1.7 160 | type: gauge 161 | help: The maximum number of process contexts this system can support - 1.3.6.1.2.1.25.1.7 162 | - name: hrMemorySize 163 | oid: 1.3.6.1.2.1.25.2.2 164 | type: gauge 165 | help: The amount of physical read-write main memory, typically RAM, contained 166 | by the host. - 1.3.6.1.2.1.25.2.2 167 | - name: hrStorageSize 168 | oid: 1.3.6.1.2.1.25.2.3.1.5 169 | type: gauge 170 | help: The size of the storage represented by this entry, in units of hrStorageAllocationUnits 171 | - 1.3.6.1.2.1.25.2.3.1.5 172 | indexes: 173 | - labelname: hrStorageIndex 174 | type: gauge 175 | - name: hrStorageUsed 176 | oid: 1.3.6.1.2.1.25.2.3.1.6 177 | type: gauge 178 | help: The amount of the storage represented by this entry that is allocated, 179 | in units of hrStorageAllocationUnits. - 1.3.6.1.2.1.25.2.3.1.6 180 | indexes: 181 | - labelname: hrStorageIndex 182 | type: gauge 183 | - name: hrProcessorLoad 184 | oid: 1.3.6.1.2.1.25.3.3.1.2 185 | type: gauge 186 | help: The average, over the last minute, of the percentage of time that this 187 | processor was not idle - 1.3.6.1.2.1.25.3.3.1.2 188 | indexes: 189 | - labelname: hrDeviceIndex 190 | type: gauge 191 | - name: ifHCOutOctets 192 | oid: 1.3.6.1.2.1.31.1.1.1.10 193 | type: counter 194 | help: The total number of octets transmitted out of the interface, including 195 | framing characters - 1.3.6.1.2.1.31.1.1.1.10 196 | indexes: 197 | - labelname: ifIndex 198 | type: gauge 199 | lookups: 200 | - labels: 201 | - ifIndex 202 | labelname: ifName 203 | oid: 1.3.6.1.2.1.31.1.1.1.1 204 | type: DisplayString 205 | - name: ifHCInOctets 206 | oid: 1.3.6.1.2.1.31.1.1.1.6 207 | type: counter 208 | help: The total number of octets received on the interface, including framing 209 | characters - 1.3.6.1.2.1.31.1.1.1.6 210 | indexes: 211 | - labelname: ifIndex 212 | type: gauge 213 | lookups: 214 | - labels: 215 | - ifIndex 216 | labelname: ifName 217 | oid: 1.3.6.1.2.1.31.1.1.1.1 218 | type: DisplayString 219 | - name: tcpMaxConn 220 | oid: 1.3.6.1.2.1.6.4 221 | type: gauge 222 | help: The limit on the total number of TCP connections the entity can support 223 | - 1.3.6.1.2.1.6.4 224 | - name: tcpActiveOpens 225 | oid: 1.3.6.1.2.1.6.5 226 | type: counter 227 | help: The number of times that TCP connections have made a direct transition 228 | to the SYN-SENT state from the CLOSED state - 1.3.6.1.2.1.6.5 229 | - name: tcpPassiveOpens 230 | oid: 1.3.6.1.2.1.6.6 231 | type: counter 232 | help: The number of times TCP connections have made a direct transition to the 233 | SYN-RCVD state from the LISTEN state - 1.3.6.1.2.1.6.6 234 | - name: tcpEstabResets 235 | oid: 1.3.6.1.2.1.6.8 236 | type: counter 237 | help: The number of times that TCP connections have made a direct transition 238 | to the CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state 239 | - 1.3.6.1.2.1.6.8 240 | - name: tcpCurrEstab 241 | oid: 1.3.6.1.2.1.6.9 242 | type: gauge 243 | help: The number of TCP connections for which the current state is either ESTABLISHED 244 | or CLOSE-WAIT. - 1.3.6.1.2.1.6.9 245 | - name: ssCpuRawIdle 246 | oid: 1.3.6.1.4.1.2021.11.53 247 | type: counter 248 | help: The number of 'ticks' (typically 1/100s) spent idle - 1.3.6.1.4.1.2021.11.53 249 | - name: memTotalReal 250 | oid: 1.3.6.1.4.1.2021.4.5 251 | type: gauge 252 | help: The total amount of real/physical memory installed on this host. - 1.3.6.1.4.1.2021.4.5 253 | - name: memAvailReal 254 | oid: 1.3.6.1.4.1.2021.4.6 255 | type: gauge 256 | help: The amount of real/physical memory currently unused or available. - 1.3.6.1.4.1.2021.4.6 257 | 258 | --------------------------------------------------------------------------------