Skip to content

Commit

Permalink
Merge pull request #20 from charlie-haley/feat/v3
Browse files Browse the repository at this point in the history
feat: controller metrics, better naming, toggle collectors
  • Loading branch information
charlie-haley authored Feb 6, 2022
2 parents 4885c84 + e0a2878 commit fd751a0
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 106 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: Check

on:
workflow_dispatch:
pull_request:

jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout the code
uses: actions/checkout@v1

- name: Set up QEMU
uses: docker/setup-qemu-action@v1

- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1

- name: Lint with golangci-lint
uses: golangci/golangci-lint-action@v2

- name: Run GoReleaser check
uses: goreleaser/[email protected]
with:
version: latest
args: build --skip-validate
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Go workspace file
go.work

# dist folder
/dist

# generated metrics table
gen-metrics-table.md
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
lint:
golangci-lint run

generate-metrics-table:
sh ./scripts/metric-markdown-table.sh
54 changes: 30 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,17 @@ COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--host value The hostname of the Omada Controller, including protocol. [$OMADA_HOST]
--username value Username of the Omada user you'd like to use to fetch metrics. [$OMADA_USER]
--password value Password for your Omada user. [$OMADA_PASS]
--port value Port on which to expose the Prometheus metrics. (default: "9202") [$OMADA_PORT]
--site value Password for your Omada user. [$OMADA_SITE]
--interval value Interval between scrapes, in seconds. (default: 5) [$OMADA_SCRAPE_INTERVAL]
--insecure Whether to skip verifying the SSL certificate on the controller. (default: false) [$OMADA_INSECURE]
--help, -h show help (default: false)
--version, -v print the version (default: false)
--host value The hostname of the Omada Controller, including protocol. [$OMADA_HOST]
--username value Username of the Omada user you'd like to use to fetch metrics. [$OMADA_USER]
--password value Password for your Omada user. [$OMADA_PASS]
--port value Port on which to expose the Prometheus metrics. (default: "9202") [$OMADA_PORT]
--site value Omada site to scrape metrics from. (default: "Default") [$OMADA_SITE]
--interval value Interval between scrapes, in seconds. (default: 5) [$OMADA_SCRAPE_INTERVAL]
--insecure Whether to skip verifying the SSL certificate on the controller. (default: false) [$OMADA_INSECURE]
--disable-go-collector Disable Go collector metrics. (default: false) [$OMADA_DISABLE_GO_COLLECTOR]
--disable-process-collector Disable process collector metrics. (default: false) [$OMADA_DISABLE_PROCESS_COLLECTOR]
--help, -h show help (default: false)
--version, -v print the version (default: false)
```

## ⚙️ Configuration
Expand All @@ -80,6 +82,8 @@ OMADA_SITE | Site you'd like to get metrics from. (default: "Defau
OMADA_PORT | Port on which to expose the Prometheus metrics. (default: 9202)
OMADA_INSECURE | Whether to skip verifying the SSL certificate on the controller. (default: false)
OMADA_SCRAPE_INTERVAL | Interval between scrapes, in seconds. (default: 5)
OMADA_DISABLE_GO_COLLECTOR | Disable Go collector metrics.
OMADA_DISABLE_PROCESS_COLLECTOR | Disable process collector metrics.

### Helm
```
Expand All @@ -94,18 +98,20 @@ omada:
```

## 📊 Metrics
Name | Description | Labels
-----------------------------------|-------------------------------------------------------------|---------------------------------------------------
omada_uptime_seconds | Uptime of the device. | device, model, version, ip, mac, site, device_type
omada_cpu_percentage | Percentage of device CPU used. | device, model, version, ip, mac, site, device_type
omada_mem_percentage | Percentage of device Memory used. | device, model, version, ip, mac, site, device_type
omada_device_need_upgrade | A boolean on whether the device needs an upgrade. | device, model, version, ip, mac, site, device_type
omada_tx_rate | The tx rate of the device. | device, model, version, ip, mac, site, device_type
omada_rx_rate | The rx rate of the device. | device, model, version, ip, mac, site, device_type
omada_poe_remain_watts | The remaining amount of PoE power for the device in watts. | device, model, version, ip, mac, site, device_type
omada_download_activity_bytes | The current download activity for the LAN client in bytes. | client, vendor, switch_port, vlan_id, ip, mac, site
omada_wlan_download_activity_bytes | The current download activity for the WLAN client in bytes. | client, vendor, ip, mac, ap_name, site, ssid, wifi_mode
omada_client_signal_dbm | The signal level for the wireless client in dBm. | device, model, version, ip, mac, site, device_type
omada_port_power_watts | The current PoE usage of the port in watts. | device, model, version, ip, mac, site, device_type
omada_port_link_status | A boolean representing the link status of the port. | device, model, version, ip, mac, site, device_type
omada_port_link_speed_mbps | Port link speed in mbps. This is the capability of the connection, not the active throughput. | device, model, version, ip, mac, site, device_type
Name|Description|Labels
|--|--|--|
omada_device_uptime_seconds | Uptime of the device. | device, model, version, ip, mac, site, device_type
omada_device_cpu_percentage | Percentage of device CPU used. | device, model, version, ip, mac, site, device_type
omada_device_mem_percentage | Percentage of device Memory used. | device, model, version, ip, mac, site, device_type
omada_device_need_upgrade | A boolean on whether the device needs an upgrade. | device, model, version, ip, mac, site, device_type
omada_device_tx_rate | The tx rate of the device. | device, model, version, ip, mac, site, device_type
omada_device_rx_rate | The rx rate of the device. | device, model, version, ip, mac, site, device_type
omada_device_poe_remain_watts | The remaining amount of PoE power for the device in watts. | device, model, version, ip, mac, site, device_type
omada_client_download_activity_bytes | The current download activity for the client in bytes. | client, vendor, switch_port, vlan_id, ip, mac, site, ap_name, ssid, wifi_mode
omada_client_signal_dbm | The signal level for the wireless client in dBm. | client, vendor, ip, mac, ap_name, site, ssid, wifi_mode
omada_port_power_watts | The current PoE usage of the port in watts. | client, vendor, switch_port, switch_mac, switch_id, vlan_id, profile, site
omada_port_link_status | A boolean representing the link status of the port. | client, vendor, switch_port, switch_mac, switch_id, vlan_id, profile, site
omada_port_link_speed_mbps | Port link speed in mbps. This is the capability of the connection, not the active throughput. | client, vendor, switch_port, switch_mac, switch_id, vlan_id, profile, site
omada_controller_uptime_seconds | Uptime of the controller. | controller_name, model, controller_version, firmware_version, mac
omada_controller_storage_used_bytes | Storage used on the controller. | storage_name, controller_name, model, controller_version, firmware_version, mac
omada_controller_storage_available_bytes | Total storage available for the controller. | storage_name, controller_name, model, controller_version, firmware_version, mac
28 changes: 21 additions & 7 deletions cmd/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@ import (

"github.com/charlie-haley/omada_exporter/pkg/api"
"github.com/charlie-haley/omada_exporter/pkg/omada"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)

var version = "development"
var (
host string
username string
password string
port string
site string
interval int
insecure bool
host string
username string
password string
port string
site string
interval int
insecure bool
goCollectorDisabled bool
processCollectorDisabled bool
)

func Run() {
Expand All @@ -41,6 +44,8 @@ func Run() {
&cli.StringFlag{Destination: &site, Name: "site", Value: "Default", Usage: "Omada site to scrape metrics from.", EnvVars: []string{"OMADA_SITE"}},
&cli.IntFlag{Destination: &interval, Name: "interval", Value: 5, Usage: "Interval between scrapes, in seconds.", EnvVars: []string{"OMADA_SCRAPE_INTERVAL"}},
&cli.BoolFlag{Destination: &insecure, Name: "insecure", Value: false, Usage: "Whether to skip verifying the SSL certificate on the controller.", EnvVars: []string{"OMADA_INSECURE"}},
&cli.BoolFlag{Destination: &goCollectorDisabled, Name: "disable-go-collector", Value: false, Usage: "Disable Go collector metrics.", EnvVars: []string{"OMADA_DISABLE_GO_COLLECTOR"}},
&cli.BoolFlag{Destination: &processCollectorDisabled, Name: "disable-process-collector", Value: false, Usage: "Disable process collector metrics.", EnvVars: []string{"OMADA_DISABLE_PROCESS_COLLECTOR"}},
}
app.Commands = []*cli.Command{
{Name: "version", Aliases: []string{"v"}, Usage: "prints the current version.",
Expand All @@ -60,6 +65,15 @@ func Run() {
}

func run(c *cli.Context) error {
if goCollectorDisabled {
// remove Go collector
prometheus.Unregister(prometheus.NewGoCollector())
}
if processCollectorDisabled {
// remove Process collector
prometheus.Unregister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
}

client, err := api.Configure(c)
if err != nil {
return err
Expand Down
40 changes: 35 additions & 5 deletions pkg/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,34 @@ import (
log "github.com/sirupsen/logrus"
)

func (c *Client) GetClients() ([]client, error) {
clientdata := clientResponse{}
// gets clients by switch mac address
func (c *Client) GetClientByPort(switchMac string, port float64) (*NetworkClient, error) {
clients, err := c.getClientsWithFilters(true, switchMac)
if err != nil {
log.Error(err)
return nil, err
}
for _, client := range clients {
if client.Port == port {
return &client, nil
}
}
return nil, nil
}

// gets all clients
func (c *Client) GetClients() ([]NetworkClient, error) {
client, err := c.getClientsWithFilters(false, "")
if err != nil {
log.Error(err)
return nil, err
}

return client, nil
}

// gets clients by filters in omada - currentl supports SwitchMac
func (c *Client) getClientsWithFilters(filtersEnabled bool, mac string) ([]NetworkClient, error) {
loggedIn, err := c.IsLoggedIn()
if err != nil {
log.Error(err)
Expand All @@ -22,7 +47,7 @@ func (c *Client) GetClients() ([]client, error) {
err := c.Login()
if err != nil || c.token == "" {
log.Error(fmt.Sprintf("Failed to login: %s", err))
return clientdata.Result.Data, err
return nil, err
}
}

Expand All @@ -37,6 +62,10 @@ func (c *Client) GetClients() ([]client, error) {
q.Add("currentPage", "1")
q.Add("currentPageSize", "10000")
q.Add("filters.active", "true")
if filtersEnabled {
q.Add("filters.switchMac=", mac)
}

req.URL.RawQuery = q.Encode()

setHeaders(req, c.token)
Expand All @@ -53,6 +82,7 @@ func (c *Client) GetClients() ([]client, error) {
return nil, err
}

clientdata := clientResponse{}
err = json.Unmarshal(body, &clientdata)

return clientdata.Result.Data, err
Expand All @@ -62,9 +92,9 @@ type clientResponse struct {
Result data `json:"result"`
}
type data struct {
Data []client `json:"data"`
Data []NetworkClient `json:"data"`
}
type client struct {
type NetworkClient struct {
Name string `json:"name"`
HostName string `json:"hostName"`
Mac string `json:"mac"`
Expand Down
70 changes: 70 additions & 0 deletions pkg/api/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package api

import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"

log "github.com/sirupsen/logrus"
)

func (c *Client) GetController() (*Controller, error) {
loggedIn, err := c.IsLoggedIn()
if err != nil {
log.Error(err)
return nil, err
}
if !loggedIn {
log.Info(fmt.Errorf("not logged in, logging in with user: %s", c.Config.String("username")))
err := c.Login()
if err != nil || c.token == "" {
log.Error(fmt.Errorf("failed to login: %s", err))
return nil, err
}
}

url := fmt.Sprintf("%s/%s/api/v2/maintenance/controllerStatus?", c.Config.String("host"), c.omadaCID)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Error(err)
return nil, err
}

setHeaders(req, c.token)
resp, err := c.httpClient.Do(req)
if err != nil {
log.Error(err)
return nil, err
}

defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error(err)
return nil, err
}

controllerData := controllerResponse{}
err = json.Unmarshal(body, &controllerData)

return &controllerData.Result, err
}

type controllerResponse struct {
Result Controller `json:"result"`
}
type Controller struct {
Name string `json:"name"`
MacAddress string `json:"macAddress"`
FirmwareVersion string `json:"firmwareVersion"`
ControllerVersion string `json:"controllerVersion"`
Model string `json:"model"`
Uptime float64 `json:"upTime"`
Storage []hwcStorage `json:"hwcStorage"`
}
type hwcStorage struct {
Name string `json:"name"`
Total float64 `json:"totalStorage"`
Used float64 `json:"usedStorage"`
}
25 changes: 19 additions & 6 deletions pkg/api/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import (
log "github.com/sirupsen/logrus"
)

func (c *Client) GetDevices() ([]device, error) {
devicedata := deviceResponse{}

func (c *Client) GetDevices() ([]Device, error) {
loggedIn, err := c.IsLoggedIn()
if err != nil {
log.Error(err)
Expand All @@ -22,7 +20,7 @@ func (c *Client) GetDevices() ([]device, error) {
err := c.Login()
if err != nil || c.token == "" {
log.Error(fmt.Errorf("failed to login: %s", err))
return devicedata.Result, err
return nil, err
}
}

Expand All @@ -47,15 +45,29 @@ func (c *Client) GetDevices() ([]device, error) {
return nil, err
}

devicedata := deviceResponse{}
err = json.Unmarshal(body, &devicedata)

var ports []Port
for i, d := range devicedata.Result {
if d.Type == "switch" {
switchPorts, err := c.GetPorts(d.Mac)
if err != nil {
return nil, fmt.Errorf("failed to get ports: %s", err)
}
ports = append(ports, switchPorts...)
device := &devicedata.Result[i]
device.Ports = ports
}
}

return devicedata.Result, err
}

type deviceResponse struct {
Result []device `json:"result"`
Result []Device `json:"result"`
}
type device struct {
type Device struct {
Name string `json:"name"`
Type string `json:"type"`
Mac string `json:"mac"`
Expand All @@ -69,4 +81,5 @@ type device struct {
TxRate float64 `json:"txRate"`
RxRate float64 `json:"rxRate"`
PoeRemain float64 `json:"poeRemain"`
Ports []Port `json:"ports"`
}
Loading

0 comments on commit fd751a0

Please sign in to comment.