Skip to content

Commit

Permalink
FEATURE: implement tcp stats metrics (#9)
Browse files Browse the repository at this point in the history
- TCP stats metrcis
- Pull Request Template
  • Loading branch information
ihatemodels authored Mar 29, 2024
1 parent b5a1cf4 commit 87d7d4a
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 15 deletions.
31 changes: 31 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Pull Request Template

## Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)

## Type of change

Please delete options that are not relevant.

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration

- [ ] Test A
- [ ] Test B

## Checklist:

- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
68 changes: 64 additions & 4 deletions internal/collector/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ import (
)

type protocolCollector struct {
log log.Logger
subsystem string
instance string
log log.Logger
subsystem string
instance string
tcpConnectionCountByState *prometheus.Desc
tcpSentPackets *prometheus.Desc
tcpReceivedPackets *prometheus.Desc
arpSentRequests *prometheus.Desc
arpReceivedRequests *prometheus.Desc
}

func init() {
Expand All @@ -28,13 +33,68 @@ func (c *protocolCollector) Register(namespace, instanceLabel string, log log.Lo
c.instance = instanceLabel
level.Debug(c.log).
Log("msg", "Registering collector", "collector", c.Name())

c.tcpConnectionCountByState = buildPrometheusDesc(c.subsystem, "tcp_connection_count_by_state",
"Number of TCP connections by state",
[]string{"state"},
)

c.tcpSentPackets = buildPrometheusDesc(c.subsystem, "tcp_sent_packets_total",
"Number of sent TCP packets ",
nil,
)

c.tcpReceivedPackets = buildPrometheusDesc(c.subsystem, "tcp_received_packets_total",
"Number of received TCP packets",
nil,
)

c.arpSentRequests = buildPrometheusDesc(c.subsystem, "arp_sent_requests_total",
"Number of sent ARP requests",
nil,
)

c.arpReceivedRequests = buildPrometheusDesc(c.subsystem, "arp_received_requests_total",
"Number of received ARP requests",
nil,
)
}

func (c *protocolCollector) Describe(ch chan<- *prometheus.Desc) {

ch <- c.tcpConnectionCountByState
ch <- c.tcpSentPackets
ch <- c.tcpReceivedPackets
ch <- c.arpSentRequests
ch <- c.arpReceivedRequests
}

func (c *protocolCollector) Update(client *opnsense.Client, ch chan<- prometheus.Metric) *opnsense.APICallError {
data, err := client.FetchProtocolStatistics()
if err != nil {
return err
}

for state, count := range data.TCPConnectionCountByState {
ch <- prometheus.MustNewConstMetric(
c.tcpConnectionCountByState, prometheus.GaugeValue, float64(count), state, c.instance,
)
}

ch <- prometheus.MustNewConstMetric(
c.tcpSentPackets, prometheus.CounterValue, float64(data.TCPSentPackets), c.instance,
)

ch <- prometheus.MustNewConstMetric(
c.tcpReceivedPackets, prometheus.CounterValue, float64(data.TCPReceivedPackets), c.instance,
)

ch <- prometheus.MustNewConstMetric(
c.arpSentRequests, prometheus.CounterValue, float64(data.ARPSentRequests), c.instance,
)

ch <- prometheus.MustNewConstMetric(
c.arpReceivedRequests, prometheus.CounterValue, float64(data.ARPReceivedRequests), c.instance,
)

return nil
}
8 changes: 3 additions & 5 deletions internal/options/ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func opsAPIKey() (string, error) {
return *opnsenseAPIKey, nil
}

// OPNSenseConfig holds the configuration for the OPNsense API.
type OPNSenseConfig struct {
Protocol string
Host string
Expand All @@ -96,11 +97,8 @@ type OPNSenseConfig struct {
Insecure bool
}

func (c *OPNSenseConfig) String() string {
return fmt.Sprintf("Protocol: %s, Host: %s, APIKey: %s, APISecret: %s, Insecure: %t",
c.Protocol, c.Host, c.APIKey, c.APISecret, c.Insecure)
}

// Validate checks if the configuration is valid.
// returns an error on any missing value
func (c *OPNSenseConfig) Validate() error {
if c.Protocol != "http" && c.Protocol != "https" {
return fmt.Errorf("protocol must be one of: [http, https]")
Expand Down
32 changes: 28 additions & 4 deletions opnsense/protocol_statistics.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,24 +258,48 @@ type protocolStatisticsResponse struct {
}

type ProtocolStatistics struct {
TCPSentPackets int
TCPReceivedPackets int
ARPSentRequests int
ARPReceivedRequests int
TCPConnectionCountByState map[string]int
}

func (c *Client) FetchProtocolStatistics() (ProtocolStatistics, *APICallError) {
var (
resp protocolStatisticsResponse
data ProtocolStatistics
)
url, ok := c.endpoints["protocolStatistics"]
if !ok {
return data, &APICallError{
return ProtocolStatistics{}, &APICallError{
Endpoint: "protocolStatistics",
StatusCode: 404,
Message: "endpoint not found in client endpoints",
}
}
if err := c.do("GET", url, nil, &resp); err != nil {
return data, err
return ProtocolStatistics{}, err
}
return data, nil

out := ProtocolStatistics{
TCPSentPackets: resp.Statistics.TCP.SentPackets,
TCPReceivedPackets: resp.Statistics.TCP.ReceivedPackets,
ARPSentRequests: resp.Statistics.Arp.SentRequests,
ARPReceivedRequests: resp.Statistics.Arp.ReceivedRequests,
TCPConnectionCountByState: map[string]int{
"CLOSED": resp.Statistics.TCP.TCPConnectionCountByState.Closed,
"LISTEN": resp.Statistics.TCP.TCPConnectionCountByState.Listen,
"SYN_SENT": resp.Statistics.TCP.TCPConnectionCountByState.SynSent,
"SYN_RCVD": resp.Statistics.TCP.TCPConnectionCountByState.SynRcvd,
"ESTABLISHED": resp.Statistics.TCP.TCPConnectionCountByState.Established,
"CLOSE_WAIT": resp.Statistics.TCP.TCPConnectionCountByState.CloseWait,
"FIN_WAIT_1": resp.Statistics.TCP.TCPConnectionCountByState.FinWait1,
"CLOSING": resp.Statistics.TCP.TCPConnectionCountByState.Closing,
"LAST_ACK": resp.Statistics.TCP.TCPConnectionCountByState.LastAck,
"FIN_WAIT_2": resp.Statistics.TCP.TCPConnectionCountByState.FinWait2,
"TIME_WAIT": resp.Statistics.TCP.TCPConnectionCountByState.TimeWait,
},
}

return out, nil
}
4 changes: 2 additions & 2 deletions opnsense/unbound_dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,11 @@ func (c *Client) FetchUnboundOverview() (UnboundDNSOverview, *APICallError) {
}
}
data.AnnswerBogusTotal, errConvertion = parseStringToInt(response.Data.Num.Answer.Bogus, url)
if err != nil {
if errConvertion != nil {
return data, errConvertion
}
data.AnswerSecureTotal, errConvertion = parseStringToInt(response.Data.Num.Answer.Secure, url)
if err != nil {
if errConvertion != nil {
return data, errConvertion
}
return data, nil
Expand Down

0 comments on commit 87d7d4a

Please sign in to comment.