initial commit

This commit is contained in:
2025-10-17 09:29:37 +03:00
parent d71905255a
commit 4d0759c479
23 changed files with 2250 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
package app
import (
"sync"
"gitea.sinav-lab.com/sinav/keenetic-exporter-v2/internal/collector"
"gitea.sinav-lab.com/sinav/keenetic-exporter-v2/internal/device"
"github.com/prometheus/client_golang/prometheus"
)
type Coordinator struct {
deviceManager *device.Manager
registry *collector.Registry
}
func NewCoordinator(dm *device.Manager, reg *collector.Registry) *Coordinator {
return &Coordinator{
deviceManager: dm,
registry: reg,
}
}
// Реализация интерфейса prometheus.Collector
func (c *Coordinator) Describe(ch chan<- *prometheus.Desc) {
collectors := c.registry.GetCollectors()
for _, col := range collectors {
col.Describe(ch)
}
}
func (c *Coordinator) Collect(ch chan<- prometheus.Metric) {
c.Scrape(ch)
}
func (c *Coordinator) Scrape(ch chan<- prometheus.Metric) {
devices := c.deviceManager.GetDevices()
collectors := c.registry.GetCollectors()
var wg sync.WaitGroup
for _, d := range devices {
wg.Add(1)
go func(dev *device.Device) {
defer wg.Done()
c.scrapeDevice(dev, collectors, ch)
}(d)
}
wg.Wait()
}
func (c *Coordinator) scrapeDevice(dev *device.Device, collectors []collector.Collector, ch chan<- prometheus.Metric) {
for _, col := range collectors {
if shouldSkipCollector(dev, col.Name()) {
continue
}
if err := col.Collect(dev, ch); err != nil {
// TODO: handle error metric
continue
}
}
}
func shouldSkipCollector(dev *device.Device, name string) bool {
for _, skip := range dev.SkipCollectors {
if skip == name {
return true
}
}
return false
}

View File

@@ -0,0 +1,54 @@
package app
import (
"context"
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
type PrometheusServer struct {
port string
coordinator *Coordinator
server *http.Server
//registry *prometheus.Registry
}
func NewPrometheusServer(port string, coordinator *Coordinator) *PrometheusServer {
// Создаем собственный реестр метрик
// registry := prometheus.NewRegistry()
return &PrometheusServer{
port: port,
coordinator: coordinator,
//registry: registry,
}
}
func (s *PrometheusServer) Start(ctx context.Context) error {
// Регистрируем coordinator как коллектор
// s.registry.MustRegister(s.coordinator)
prometheus.MustRegister(s.coordinator)
mux := http.NewServeMux()
// Используем наш реестр вместо глобального
// mux.Handle("/metrics", promhttp.HandlerFor(s.registry, promhttp.HandlerOpts{}))
mux.Handle("/metrics", promhttp.Handler())
mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
s.server = &http.Server{
Addr: ":" + s.port,
Handler: mux,
}
go func() {
<-ctx.Done()
s.server.Shutdown(context.Background())
}()
return s.server.ListenAndServe()
}