mirror of https://github.com/h44z/wg-portal.git
				
				
				
			
		
			
				
	
	
		
			136 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
package adapters
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"net/http"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/h44z/wg-portal/internal"
 | 
						|
	"github.com/h44z/wg-portal/internal/config"
 | 
						|
	"github.com/h44z/wg-portal/internal/domain"
 | 
						|
	"github.com/prometheus/client_golang/prometheus"
 | 
						|
	"github.com/prometheus/client_golang/prometheus/promauto"
 | 
						|
	"github.com/prometheus/client_golang/prometheus/promhttp"
 | 
						|
	"github.com/sirupsen/logrus"
 | 
						|
)
 | 
						|
 | 
						|
type MetricsServer struct {
 | 
						|
	*http.Server
 | 
						|
 | 
						|
	ifaceReceivedBytesTotal  *prometheus.GaugeVec
 | 
						|
	ifaceSendBytesTotal      *prometheus.GaugeVec
 | 
						|
	peerIsConnected          *prometheus.GaugeVec
 | 
						|
	peerLastHandshakeSeconds *prometheus.GaugeVec
 | 
						|
	peerReceivedBytesTotal   *prometheus.GaugeVec
 | 
						|
	peerSendBytesTotal       *prometheus.GaugeVec
 | 
						|
}
 | 
						|
 | 
						|
// Wireguard metrics labels
 | 
						|
var (
 | 
						|
	ifaceLabels = []string{"interface"}
 | 
						|
	peerLabels  = []string{"interface", "addresses", "id", "name"}
 | 
						|
)
 | 
						|
 | 
						|
// NewMetricsServer returns a new prometheus server
 | 
						|
func NewMetricsServer(cfg *config.Config) *MetricsServer {
 | 
						|
	reg := prometheus.NewRegistry()
 | 
						|
 | 
						|
	mux := http.NewServeMux()
 | 
						|
	mux.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg}))
 | 
						|
 | 
						|
	return &MetricsServer{
 | 
						|
		Server: &http.Server{
 | 
						|
			Addr:    cfg.Statistics.ListeningAddress,
 | 
						|
			Handler: mux,
 | 
						|
		},
 | 
						|
 | 
						|
		ifaceReceivedBytesTotal: promauto.With(reg).NewGaugeVec(
 | 
						|
			prometheus.GaugeOpts{
 | 
						|
				Name: "wireguard_interface_received_bytes_total",
 | 
						|
				Help: "Bytes received througth the interface.",
 | 
						|
			}, ifaceLabels,
 | 
						|
		),
 | 
						|
		ifaceSendBytesTotal: promauto.With(reg).NewGaugeVec(
 | 
						|
			prometheus.GaugeOpts{
 | 
						|
				Name: "wireguard_interface_sent_bytes_total",
 | 
						|
				Help: "Bytes sent through the interface.",
 | 
						|
			}, ifaceLabels,
 | 
						|
		),
 | 
						|
 | 
						|
		peerIsConnected: promauto.With(reg).NewGaugeVec(
 | 
						|
			prometheus.GaugeOpts{
 | 
						|
				Name: "wireguard_peer_up",
 | 
						|
				Help: "Peer connection state (boolean: 1/0).",
 | 
						|
			}, peerLabels,
 | 
						|
		),
 | 
						|
		peerLastHandshakeSeconds: promauto.With(reg).NewGaugeVec(
 | 
						|
			prometheus.GaugeOpts{
 | 
						|
				Name: "wireguard_peer_last_handshake_seconds",
 | 
						|
				Help: "Seconds from the last handshake with the peer.",
 | 
						|
			}, peerLabels,
 | 
						|
		),
 | 
						|
		peerReceivedBytesTotal: promauto.With(reg).NewGaugeVec(
 | 
						|
			prometheus.GaugeOpts{
 | 
						|
				Name: "wireguard_peer_received_bytes_total",
 | 
						|
				Help: "Bytes received from the peer.",
 | 
						|
			}, peerLabels,
 | 
						|
		),
 | 
						|
		peerSendBytesTotal: promauto.With(reg).NewGaugeVec(
 | 
						|
			prometheus.GaugeOpts{
 | 
						|
				Name: "wireguard_peer_sent_bytes_total",
 | 
						|
				Help: "Bytes sent to the peer.",
 | 
						|
			}, peerLabels,
 | 
						|
		),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Run starts the metrics server
 | 
						|
func (m *MetricsServer) Run(ctx context.Context) {
 | 
						|
	// Run the metrics server in a goroutine
 | 
						|
	go func() {
 | 
						|
		if err := m.ListenAndServe(); err != nil && err != http.ErrServerClosed {
 | 
						|
			logrus.Errorf("metrics service on %s exited: %v", m.Addr, err)
 | 
						|
		}
 | 
						|
	}()
 | 
						|
 | 
						|
	logrus.Infof("started metrics service on %s", m.Addr)
 | 
						|
 | 
						|
	// Wait for the context to be done
 | 
						|
	<-ctx.Done()
 | 
						|
 | 
						|
	// Create a context with timeout for the shutdown process
 | 
						|
	shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
 | 
						|
	defer cancel()
 | 
						|
 | 
						|
	// Attempt to gracefully shutdown the metrics server
 | 
						|
	if err := m.Shutdown(shutdownCtx); err != nil {
 | 
						|
		logrus.Errorf("metrics service on %s shutdown failed: %v", m.Addr, err)
 | 
						|
	} else {
 | 
						|
		logrus.Infof("metrics service on %s shutdown gracefully", m.Addr)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// UpdateInterfaceMetrics updates the metrics for the given interface
 | 
						|
func (m *MetricsServer) UpdateInterfaceMetrics(status domain.InterfaceStatus) {
 | 
						|
	labels := []string{string(status.InterfaceId)}
 | 
						|
	m.ifaceReceivedBytesTotal.WithLabelValues(labels...).Set(float64(status.BytesReceived))
 | 
						|
	m.ifaceSendBytesTotal.WithLabelValues(labels...).Set(float64(status.BytesTransmitted))
 | 
						|
}
 | 
						|
 | 
						|
// UpdatePeerMetrics updates the metrics for the given peer
 | 
						|
func (m *MetricsServer) UpdatePeerMetrics(peer *domain.Peer, status domain.PeerStatus) {
 | 
						|
	labels := []string{
 | 
						|
		string(peer.InterfaceIdentifier),
 | 
						|
		string(peer.Interface.AddressStr()),
 | 
						|
		string(status.PeerId),
 | 
						|
		string(peer.DisplayName),
 | 
						|
	}
 | 
						|
 | 
						|
	if status.LastHandshake != nil {
 | 
						|
		m.peerLastHandshakeSeconds.WithLabelValues(labels...).Set(float64(status.LastHandshake.Unix()))
 | 
						|
	}
 | 
						|
	m.peerReceivedBytesTotal.WithLabelValues(labels...).Set(float64(status.BytesReceived))
 | 
						|
	m.peerSendBytesTotal.WithLabelValues(labels...).Set(float64(status.BytesTransmitted))
 | 
						|
	m.peerIsConnected.WithLabelValues(labels...).Set(internal.BoolToFloat64(status.IsConnected()))
 | 
						|
}
 |