Files
glpi-ai-agent/internal/metrics/metrics.go
T
groot 4cfdac042d
release-tag / release-image (push) Successful in 1m35s
Update GLPI-Knowledge
2026-07-28 14:35:03 +02:00

87 lines
3.3 KiB
Go

package metrics
import (
"fmt"
"io"
"sync"
"sync/atomic"
"time"
)
type Metrics struct {
Started time.Time
Processed atomic.Uint64
Skipped atomic.Uint64
Errors atomic.Uint64
CategoryChanged atomic.Uint64
Replies atomic.Uint64
Polls atomic.Uint64
WebhookEvents atomic.Uint64
ContextFetches atomic.Uint64
ContextErrors atomic.Uint64
QueueDepth atomic.Int64
mu sync.RWMutex
lastPoll time.Time
glpiOK bool
ollamaOK bool
knowledgeDocs int
glpiKBOK bool
glpiKBDocs int
glpiKBLastSync time.Time
glpiKBLastError string
}
func New() *Metrics { return &Metrics{Started: time.Now()} }
func (m *Metrics) SetLastPoll(t time.Time) { m.mu.Lock(); m.lastPoll = t; m.mu.Unlock() }
func (m *Metrics) LastPoll() time.Time { m.mu.RLock(); defer m.mu.RUnlock(); return m.lastPoll }
func (m *Metrics) SetHealth(glpi, ollama bool) {
m.mu.Lock()
m.glpiOK = glpi
m.ollamaOK = ollama
m.mu.Unlock()
}
func (m *Metrics) Health() (bool, bool) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.glpiOK, m.ollamaOK
}
func (m *Metrics) SetKnowledgeDocs(n int) { m.mu.Lock(); m.knowledgeDocs = n; m.mu.Unlock() }
func (m *Metrics) KnowledgeDocs() int { m.mu.RLock(); defer m.mu.RUnlock(); return m.knowledgeDocs }
func (m *Metrics) SetGLPIKBStatus(ok bool, docs int, lastSync time.Time, lastErr string) {
m.mu.Lock()
m.glpiKBOK = ok
m.glpiKBDocs = docs
m.glpiKBLastSync = lastSync
m.glpiKBLastError = lastErr
m.mu.Unlock()
}
func (m *Metrics) GLPIKBStatus() (bool, int, time.Time, string) {
m.mu.RLock()
defer m.mu.RUnlock()
return m.glpiKBOK, m.glpiKBDocs, m.glpiKBLastSync, m.glpiKBLastError
}
func (m *Metrics) WritePrometheus(w io.Writer) {
g, o := m.Health()
boolf := func(v bool) int {
if v {
return 1
}
return 0
}
fmt.Fprintf(w, "# TYPE glpi_agent_processed_total counter\nglpi_agent_processed_total %d\n", m.Processed.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_skipped_total counter\nglpi_agent_skipped_total %d\n", m.Skipped.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_errors_total counter\nglpi_agent_errors_total %d\n", m.Errors.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_category_changes_total counter\nglpi_agent_category_changes_total %d\n", m.CategoryChanged.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_replies_total counter\nglpi_agent_replies_total %d\n", m.Replies.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_context_fetches_total counter\nglpi_agent_context_fetches_total %d\n", m.ContextFetches.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_context_errors_total counter\nglpi_agent_context_errors_total %d\n", m.ContextErrors.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_queue_depth gauge\nglpi_agent_queue_depth %d\n", m.QueueDepth.Load())
fmt.Fprintf(w, "# TYPE glpi_agent_glpi_up gauge\nglpi_agent_glpi_up %d\n", boolf(g))
fmt.Fprintf(w, "# TYPE glpi_agent_ollama_up gauge\nglpi_agent_ollama_up %d\n", boolf(o))
fmt.Fprintf(w, "# TYPE glpi_agent_knowledge_documents gauge\nglpi_agent_knowledge_documents %d\n", m.KnowledgeDocs())
kbOK, kbDocs, _, _ := m.GLPIKBStatus()
fmt.Fprintf(w, "# TYPE glpi_agent_glpi_kb_up gauge\nglpi_agent_glpi_kb_up %d\n", boolf(kbOK))
fmt.Fprintf(w, "# TYPE glpi_agent_glpi_kb_documents gauge\nglpi_agent_glpi_kb_documents %d\n", kbDocs)
}