Documentation
¶
Overview ¶
Package handler provides HTTP request handling for Heimdall.
Index ¶
- func FilterAlertsResponse(ctx context.Context, body []byte, matchers []*labels.Matcher) ([]byte, error)
- func FilterRulesResponse(ctx context.Context, body []byte, matchers []*labels.Matcher) ([]byte, error)
- func JWTMiddleware(cfg config.JWTConfig) gin.HandlerFunc
- func MatchLabels(ruleLabels map[string]string, enforced []*labels.Matcher) bool
- func MetricsMiddleware(m *Metrics) gin.HandlerFunc
- func NormalizeFilters(filters []string) string
- func PanicRecoveryMiddleware() gin.HandlerFunc
- func ParseFilters(filters []string) ([]*labels.Matcher, error)
- func RespondError(c *gin.Context, status int, code, message string)
- func RewriteMatchParams(ctx context.Context, matchParams []string, matchers []*labels.Matcher) ([]string, error)
- func RewriteQuery(ctx context.Context, query string, matchers []*labels.Matcher) (string, error)
- func SetIdentity(ctx context.Context, id *Identity) context.Context
- func TracingMiddleware() gin.HandlerFunc
- type Action
- type Alert
- type AlertsData
- type AlertsResponse
- type CachedTenantLister
- type ErrorResponse
- type FanOutEngine
- func (fe *FanOutEngine) AuthorizeWrite(ctx context.Context, identity *Identity, tenantIDs []string, action Action) (string, error)
- func (fe *FanOutEngine) Dispatch(ctx context.Context, groups []filterGroup, originalReq *http.Request, ...) ([]byte, int, error)
- func (fe *FanOutEngine) EvaluateTenants(ctx context.Context, identity *Identity, tenantIDs []string, action Action, ...) ([]filterGroup, error)
- func (fe *FanOutEngine) ForwardWrite(ctx context.Context, tenantIDs []string, originalReq *http.Request) ([]byte, int, error)
- type Handler
- type Identity
- type Metrics
- type OPAClient
- type OPAInput
- type OPAResponse
- type OPAResult
- type Rule
- type RuleGroup
- type RulesData
- type RulesResponse
- type TenantLister
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FilterAlertsResponse ¶
func FilterAlertsResponse(ctx context.Context, body []byte, matchers []*labels.Matcher) ([]byte, error)
FilterAlertsResponse filters a /api/v1/alerts response, keeping only alerts whose labels match ALL enforced matchers. If matchers is nil or empty, the body is returned unchanged (bypass fast path).
func FilterRulesResponse ¶
func FilterRulesResponse(ctx context.Context, body []byte, matchers []*labels.Matcher) ([]byte, error)
FilterRulesResponse filters a /api/v1/rules response, keeping only rules whose labels match ALL enforced matchers. Empty groups are removed. If matchers is nil or empty, the body is returned unchanged (bypass fast path).
func JWTMiddleware ¶
func JWTMiddleware(cfg config.JWTConfig) gin.HandlerFunc
JWTMiddleware creates a Gin middleware that validates JWTs. It extracts sub → user_id and the configured groups claim → groups. Any validation failure results in a 401.
func MatchLabels ¶
MatchLabels checks if ALL enforced matchers match against the given label set.
func MetricsMiddleware ¶
func MetricsMiddleware(m *Metrics) gin.HandlerFunc
MetricsMiddleware records request count and duration for every HTTP request.
func NormalizeFilters ¶
NormalizeFilters deduplicates, sorts, and serializes filters deterministically for use as a canonical grouping key in fan-out.
func PanicRecoveryMiddleware ¶
func PanicRecoveryMiddleware() gin.HandlerFunc
PanicRecoveryMiddleware catches panics in request handling and converts them to 500 responses via RespondError.
func ParseFilters ¶
ParseFilters parses filter strings (e.g., `env="prod"`) into label matchers.
func RespondError ¶
RespondError writes a standardized JSON error response. If the request context is canceled or deadline exceeded, it automatically transforms the response to a 499 Client Closed Request mapping to enforce invariants.
func RewriteMatchParams ¶
func RewriteMatchParams(ctx context.Context, matchParams []string, matchers []*labels.Matcher) ([]string, error)
RewriteMatchParams rewrites a list of match[] parameters (used by /api/v1/series).
func RewriteQuery ¶
RewriteQuery parses a PromQL query, injects label matchers into every VectorSelector in the AST, and returns the re-rendered query string. This is the ONLY way to inject filters — never use regex or string replacement.
func SetIdentity ¶
SetIdentity stores the identity in the request context.
func TracingMiddleware ¶
func TracingMiddleware() gin.HandlerFunc
TracingMiddleware extracts traceparent, starts a root span, and attaches trace_id and span_id to all slog logs.
Types ¶
type Alert ¶
type Alert struct {
Labels map[string]string `json:"labels"`
Annotations map[string]string `json:"annotations,omitempty"`
State string `json:"state"`
ActiveAt string `json:"activeAt,omitempty"`
Value string `json:"value,omitempty"`
}
Alert represents a single alert.
type AlertsData ¶
type AlertsData struct {
Alerts []Alert `json:"alerts"`
}
AlertsData holds the alerts from an alerts response.
type AlertsResponse ¶
type AlertsResponse struct {
Status string `json:"status"`
Data AlertsData `json:"data"`
}
AlertsResponse represents the Prometheus /api/v1/alerts response.
type CachedTenantLister ¶
type CachedTenantLister struct {
// contains filtered or unexported fields
}
CachedTenantLister adds an in-memory TTL cache to an underlying TenantLister and reports cache hits and misses via the metrics engine.
func NewCachedTenantLister ¶
func NewCachedTenantLister(underlying TenantLister, ttl time.Duration, metrics *Metrics) *CachedTenantLister
NewCachedTenantLister wraps a TenantLister with a TTL cache and metrics tracking.
func (*CachedTenantLister) ListTenantIDs ¶
func (c *CachedTenantLister) ListTenantIDs(ctx context.Context) ([]string, error)
ListTenantIDs returns tenant IDs from the cache if still valid; otherwise refreshes from the underlying lister.
type ErrorResponse ¶
ErrorResponse is the standard JSON error envelope. All HTTP errors MUST use this format.
type FanOutEngine ¶
type FanOutEngine struct {
// contains filtered or unexported fields
}
FanOutEngine orchestrates multi-tenant fan-out with bounded concurrency.
func NewFanOutEngine ¶
func NewFanOutEngine(opaClient OPAClient, cfg config.MimirConfig, fanOutCfg config.FanOutConfig, transport http.RoundTripper, metrics *Metrics) *FanOutEngine
NewFanOutEngine creates a new FanOutEngine with the given configuration.
func (*FanOutEngine) AuthorizeWrite ¶
func (fe *FanOutEngine) AuthorizeWrite(ctx context.Context, identity *Identity, tenantIDs []string, action Action) (string, error)
AuthorizeWrite evaluates OPA for each tenant for write actions. Returns the denied tenant ID and error, or empty string and nil on success.
func (*FanOutEngine) Dispatch ¶
func (fe *FanOutEngine) Dispatch(ctx context.Context, groups []filterGroup, originalReq *http.Request, action Action) ([]byte, int, error)
Dispatch sends parallel upstream requests to Mimir for each filter group, using bounded concurrency. Returns merged response body.
func (*FanOutEngine) EvaluateTenants ¶
func (fe *FanOutEngine) EvaluateTenants(ctx context.Context, identity *Identity, tenantIDs []string, action Action, resource string) ([]filterGroup, error)
EvaluateTenants runs OPA authorization for each tenant and returns allowed tenants grouped by their canonical filter signature for native federation.
func (*FanOutEngine) ForwardWrite ¶
func (fe *FanOutEngine) ForwardWrite(ctx context.Context, tenantIDs []string, originalReq *http.Request) ([]byte, int, error)
ForwardWrite forwards a write request byte-for-byte to the upstream Mimir. No body inspection, no PromQL parsing, no filter injection — authorize only.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler holds the dependencies for HTTP request handling.
func NewHandler ¶
NewHandler creates a new Handler.
func (*Handler) RegisterRoutes ¶
RegisterRoutes sets up the Gin router with all middleware and routes.
func (*Handler) WithTenantLister ¶
func (h *Handler) WithTenantLister(tl TenantLister)
WithTenantLister enables automatic tenant resolution for read actions when the X-Scope-OrgID header is absent.
type Identity ¶
Identity holds the user identity extracted from the JWT.
func GetIdentity ¶
GetIdentity retrieves the identity from the request context.
func MustGetIdentity ¶
MustGetIdentity retrieves the identity from the HTTP request context or panics.
type Metrics ¶
type Metrics struct {
// contains filtered or unexported fields
}
Metrics holds all Prometheus metrics for Heimdall.
func NewMetrics ¶
NewMetrics registers all Heimdall metrics with the OTel meter provider.
func (*Metrics) RecordBundleRebuild ¶
RecordBundleRebuild increments the bundle rebuild counter (Rule 235).
type OPAClient ¶
OPAClient defines the interface for communicating with the OPA REST API.
func NewOPAClient ¶
func NewOPAClient(baseURL, policyPath string, timeout time.Duration, transport http.RoundTripper, metrics *Metrics) OPAClient
NewOPAClient creates a new OPA client. If transport is non-nil, it is used for authentication injection.
type OPAInput ¶
type OPAInput struct {
UserID string `json:"user_id"`
Groups []string `json:"groups"`
TenantID string `json:"tenant_id"`
Resource string `json:"resource"`
Action Action `json:"action"`
}
OPAInput is the input document sent to OPA for evaluation.
type OPAResponse ¶
type OPAResponse struct {
Result OPAResult `json:"result"`
}
OPAResponse wraps the OPA REST API response.
type OPAResult ¶
type OPAResult struct {
Allow bool `json:"allow"`
EffectiveFilters []string `json:"effective_filters"`
AccessibleTenants []string `json:"accessible_tenants"`
}
OPAResult is the result from OPA policy evaluation.
type Rule ¶
type Rule struct {
Name string `json:"name"`
Query string `json:"query,omitempty"`
Duration float64 `json:"duration,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
State string `json:"state,omitempty"`
Health string `json:"health,omitempty"`
Type string `json:"type"`
// Additional fields preserved as raw JSON
Alerts json.RawMessage `json:"alerts,omitempty"`
}
Rule represents a single rule within a group.
type RuleGroup ¶
type RuleGroup struct {
Name string `json:"name"`
File string `json:"file"`
Rules []Rule `json:"rules"`
}
RuleGroup represents a group of rules.
type RulesData ¶
type RulesData struct {
Groups []RuleGroup `json:"groups"`
}
RulesData holds the groups from a rules response.
type RulesResponse ¶
RulesResponse represents the Prometheus /api/v1/rules response.