mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-11 02:55:51 +00:00
c253495045
Change-source: pulse-maintainer
149 lines
4.5 KiB
Go
149 lines
4.5 KiB
Go
package api
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/monitoring"
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
var errTenantMonitorUnavailable = errors.New("tenant monitor unavailable")
|
|
|
|
// getMonitor returns the tenant-specific monitor instance for the request.
|
|
// It uses the OrgID from the context (injected by TenantMiddleware).
|
|
// Non-default orgs fail closed when tenant monitor resolution is unavailable.
|
|
func (r *Router) getMonitor(req *http.Request) (*monitoring.Monitor, error) {
|
|
orgID := GetOrgID(req.Context())
|
|
if orgID == "" || orgID == "default" {
|
|
return r.monitor, nil
|
|
}
|
|
if r.mtMonitor == nil {
|
|
return nil, errTenantMonitorUnavailable
|
|
}
|
|
|
|
return r.mtMonitor.GetMonitor(orgID)
|
|
}
|
|
|
|
// MultiTenantStateProvider wraps a MultiTenantMonitor to provide state for specific tenants.
|
|
type MultiTenantStateProvider struct {
|
|
mtMonitor *monitoring.MultiTenantMonitor
|
|
defaultMonitor *monitoring.Monitor
|
|
}
|
|
|
|
// NewMultiTenantStateProvider creates a new tenant state provider.
|
|
func NewMultiTenantStateProvider(mtm *monitoring.MultiTenantMonitor, defaultM *monitoring.Monitor) *MultiTenantStateProvider {
|
|
return &MultiTenantStateProvider{
|
|
mtMonitor: mtm,
|
|
defaultMonitor: defaultM,
|
|
}
|
|
}
|
|
|
|
func (p *MultiTenantStateProvider) monitorForTenant(orgID string) *monitoring.Monitor {
|
|
if orgID == "" || orgID == "default" {
|
|
return p.defaultMonitor
|
|
}
|
|
|
|
if p.mtMonitor != nil {
|
|
monitor, err := p.mtMonitor.GetMonitor(orgID)
|
|
if err != nil {
|
|
log.Warn().Err(err).Str("org_id", orgID).Msg("Failed to get tenant monitor")
|
|
return nil
|
|
}
|
|
return monitor
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UnifiedReadStateForTenant returns the canonical typed unified read-state for a
|
|
// specific tenant, falling back to a snapshot-backed adapter only when the
|
|
// monitor has not been wired with a resource store yet.
|
|
func (p *MultiTenantStateProvider) UnifiedReadStateForTenant(orgID string) unifiedresources.ReadState {
|
|
monitor := p.monitorForTenant(orgID)
|
|
if monitor == nil {
|
|
return nil
|
|
}
|
|
return monitor.GetUnifiedReadStateOrSnapshot()
|
|
}
|
|
|
|
// UnifiedResourceSnapshotForTenant returns the canonical unified-resource seed
|
|
// for a specific tenant, along with its freshness marker.
|
|
func (p *MultiTenantStateProvider) UnifiedResourceSnapshotForTenant(orgID string) ([]unifiedresources.Resource, time.Time) {
|
|
monitor := p.monitorForTenant(orgID)
|
|
if monitor == nil {
|
|
return nil, time.Time{}
|
|
}
|
|
|
|
return monitor.UnifiedResourceSnapshot()
|
|
}
|
|
|
|
// ResourceHealthAlertsForTenant returns only the minimal alert facts needed by
|
|
// the resource health projection, resolved from the same tenant monitor as the
|
|
// resource seed.
|
|
func (p *MultiTenantStateProvider) ResourceHealthAlertsForTenant(orgID string) []unifiedresources.ResourceHealthAlert {
|
|
monitor := p.monitorForTenant(orgID)
|
|
if monitor == nil {
|
|
return nil
|
|
}
|
|
active := monitor.ActiveAlertsSnapshot()
|
|
out := make([]unifiedresources.ResourceHealthAlert, 0, len(active))
|
|
for _, alert := range active {
|
|
out = append(out, unifiedresources.ResourceHealthAlert{
|
|
ResourceID: alert.ResourceID,
|
|
Level: alert.Level,
|
|
Type: alert.Type,
|
|
})
|
|
}
|
|
return out
|
|
}
|
|
|
|
// SetMultiTenantMonitor updates the multi-tenant monitor manager.
|
|
// Used during reload.
|
|
func (r *Router) SetMultiTenantMonitor(mtm *monitoring.MultiTenantMonitor) {
|
|
r.mtMonitor = mtm
|
|
if r.configHandlers != nil {
|
|
r.configHandlers.SetMultiTenantMonitor(mtm)
|
|
r.configHandlers.SetConfig(r.config)
|
|
}
|
|
if r.alertHandlers != nil {
|
|
r.alertHandlers.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if r.notificationHandlers != nil {
|
|
r.notificationHandlers.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if r.dockerAgentHandlers != nil {
|
|
r.dockerAgentHandlers.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if r.unifiedAgentHandlers != nil {
|
|
r.unifiedAgentHandlers.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if r.kubernetesAgentHandlers != nil {
|
|
r.kubernetesAgentHandlers.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if r.systemSettingsHandler != nil {
|
|
r.systemSettingsHandler.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if r.aiSettingsHandler != nil {
|
|
r.aiSettingsHandler.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if r.aiHandler != nil {
|
|
r.aiHandler.SetMultiTenantMonitor(mtm)
|
|
}
|
|
if mtm != nil {
|
|
if m, err := mtm.GetMonitor("default"); err == nil {
|
|
r.monitor = m
|
|
r.bindDefaultMetadataStores(m)
|
|
}
|
|
mtm.SetMonitorInitializer(r.configureMonitorDependencies)
|
|
}
|
|
r.configureMetadataProviderFactory()
|
|
|
|
// Wire tenant state provider to resource handlers
|
|
if r.resourceHandlers != nil {
|
|
r.resourceHandlers.SetTenantStateProvider(NewMultiTenantStateProvider(mtm, r.monitor))
|
|
}
|
|
}
|